xref: /petsc/src/mat/interface/matrix.c (revision 9140fee14acbea959c6ed74f4836a1a89f708038)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51   MatSetRandom - Sets all components of a matrix to random numbers.
52 
53   Logically Collective
54 
55   Input Parameters:
56 + x    - the matrix
57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60   Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67   Level: intermediate
68 
69   Notes:
70   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
71 
72   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
73 
74   It generates an error if used on unassembled sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109   Logically Collective
110 
111   Input Parameter:
112 . mat - the factored matrix
113 
114   Output Parameters:
115 + pivot - the pivot value computed
116 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119   Level: advanced
120 
121   Notes:
122   This routine does not work for factorizations done with external packages.
123 
124   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
130 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
149 . mat - the factored matrix
150 
151   Output Parameter:
152 . err - the error code
153 
154   Level: advanced
155 
156   Note:
157   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172   MatFactorClearError - clears the error code in a factorization
173 
174   Logically Collective
175 
176   Input Parameter:
177 . mat - the factored matrix
178 
179   Level: developer
180 
181   Note:
182   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 . mat - the matrix
257 
258   Output Parameter:
259 . keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264   `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscAssertPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282   MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 . mat - the matrix
286 
287   Output Parameter:
288 . zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293   `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscAssertPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323   Not Collective
324 
325   Input Parameter:
326 . A - the matrix
327 
328   Output Parameter:
329 . a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331   Level: advanced
332 
333   Notes:
334   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscAssertPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361   Collective
362 
363   Input Parameter:
364 . mat - the matrix
365 
366   Output Parameter:
367 . trace - the sum of the diagonal entries
368 
369   Level: advanced
370 
371 .seealso: [](ch_matrices), `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscAssertPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388   MatRealPart - Zeros out the imaginary part of the matrix
389 
390   Logically Collective
391 
392   Input Parameter:
393 . mat - the matrix
394 
395   Level: advanced
396 
397 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414   Collective
415 
416   Input Parameter:
417 . mat - the matrix
418 
419   Output Parameters:
420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
421 - ghosts  - the global indices of the ghost points
422 
423   Level: advanced
424 
425   Note:
426   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
427 
428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448   Logically Collective
449 
450   Input Parameter:
451 . mat - the matrix
452 
453   Level: advanced
454 
455 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
471 
472   Not Collective
473 
474   Input Parameter:
475 . mat - the matrix
476 
477   Output Parameters:
478 + missing - is any diagonal entry missing
479 - dd      - first diagonal entry that is missing (optional) on this process
480 
481   Level: advanced
482 
483   Note:
484   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
485 
486 .seealso: [](ch_matrices), `Mat`
487 @*/
488 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
489 {
490   PetscFunctionBegin;
491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
492   PetscValidType(mat, 1);
493   PetscAssertPointer(missing, 2);
494   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
495   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
496   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
497   PetscFunctionReturn(PETSC_SUCCESS);
498 }
499 
500 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
501 /*@C
502   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
503   for each row that you get to ensure that your application does
504   not bleed memory.
505 
506   Not Collective
507 
508   Input Parameters:
509 + mat - the matrix
510 - row - the row to get
511 
512   Output Parameters:
513 + ncols - if not `NULL`, the number of nonzeros in `row`
514 . cols  - if not `NULL`, the column numbers
515 - vals  - if not `NULL`, the numerical values
516 
517   Level: advanced
518 
519   Notes:
520   This routine is provided for people who need to have direct access
521   to the structure of a matrix.  We hope that we provide enough
522   high-level matrix routines that few users will need it.
523 
524   `MatGetRow()` always returns 0-based column indices, regardless of
525   whether the internal representation is 0-based (default) or 1-based.
526 
527   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
528   not wish to extract these quantities.
529 
530   The user can only examine the values extracted with `MatGetRow()`;
531   the values CANNOT be altered.  To change the matrix entries, one
532   must use `MatSetValues()`.
533 
534   You can only have one call to `MatGetRow()` outstanding for a particular
535   matrix at a time, per processor. `MatGetRow()` can only obtain rows
536   associated with the given processor, it cannot get rows from the
537   other processors; for that we suggest using `MatCreateSubMatrices()`, then
538   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
539   is in the global number of rows.
540 
541   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
542 
543   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
544 
545   Fortran Note:
546   The calling sequence is
547 .vb
548    MatGetRow(matrix,row,ncols,cols,values,ierr)
549          Mat     matrix (input)
550          integer row    (input)
551          integer ncols  (output)
552          integer cols(maxcols) (output)
553          double precision (or double complex) values(maxcols) output
554 .ve
555   where maxcols >= maximum nonzeros in any row of the matrix.
556 
557 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@
578   MatConjugate - replaces the matrix values with their complex conjugates
579 
580   Logically Collective
581 
582   Input Parameter:
583 . mat - the matrix
584 
585   Level: advanced
586 
587 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604   Not Collective
605 
606   Input Parameters:
607 + mat   - the matrix
608 . row   - the row to get
609 . ncols - the number of nonzeros
610 . cols  - the columns of the nonzeros
611 - vals  - if nonzero the column values
612 
613   Level: advanced
614 
615   Notes:
616   This routine should be called after you have finished examining the entries.
617 
618   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
619   us of the array after it has been restored. If you pass `NULL`, it will
620   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
621 
622   Fortran Notes:
623   The calling sequence is
624 .vb
625    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
626       Mat     matrix (input)
627       integer row    (input)
628       integer ncols  (output)
629       integer cols(maxcols) (output)
630       double precision (or double complex) values(maxcols) output
631 .ve
632   Where maxcols >= maximum nonzeros in any row of the matrix.
633 
634   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
635   before another call to `MatGetRow()` can be made.
636 
637 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
638 @*/
639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
640 {
641   PetscFunctionBegin;
642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
643   if (ncols) PetscAssertPointer(ncols, 3);
644   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
645   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
646   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
647   if (ncols) *ncols = 0;
648   if (cols) *cols = NULL;
649   if (vals) *vals = NULL;
650   PetscFunctionReturn(PETSC_SUCCESS);
651 }
652 
653 /*@
654   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
655   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
656 
657   Not Collective
658 
659   Input Parameter:
660 . mat - the matrix
661 
662   Level: advanced
663 
664   Note:
665   The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
666 
667 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
668 @*/
669 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
670 {
671   PetscFunctionBegin;
672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
673   PetscValidType(mat, 1);
674   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
676   MatCheckPreallocated(mat, 1);
677   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
678   PetscUseTypeMethod(mat, getrowuppertriangular);
679   PetscFunctionReturn(PETSC_SUCCESS);
680 }
681 
682 /*@
683   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
684 
685   Not Collective
686 
687   Input Parameter:
688 . mat - the matrix
689 
690   Level: advanced
691 
692   Note:
693   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
694 
695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, restorerowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@C
711   MatSetOptionsPrefix - Sets the prefix used for searching for all
712   `Mat` options in the database.
713 
714   Logically Collective
715 
716   Input Parameters:
717 + A      - the matrix
718 - prefix - the prefix to prepend to all option names
719 
720   Level: advanced
721 
722   Notes:
723   A hyphen (-) must NOT be given at the beginning of the prefix name.
724   The first character of all runtime options is AUTOMATICALLY the hyphen.
725 
726   This is NOT used for options for the factorization of the matrix. Normally the
727   prefix is automatically passed in from the PC calling the factorization. To set
728   it directly use  `MatSetOptionsPrefixFactor()`
729 
730 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
731 @*/
732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
733 {
734   PetscFunctionBegin;
735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
736   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 /*@C
741   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
742   for matrices created with `MatGetFactor()`
743 
744   Logically Collective
745 
746   Input Parameters:
747 + A      - the matrix
748 - prefix - the prefix to prepend to all option names for the factored matrix
749 
750   Level: developer
751 
752   Notes:
753   A hyphen (-) must NOT be given at the beginning of the prefix name.
754   The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
757   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
758 
759 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
760 @*/
761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
762 {
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
765   if (prefix) {
766     PetscAssertPointer(prefix, 2);
767     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
768     if (prefix != A->factorprefix) {
769       PetscCall(PetscFree(A->factorprefix));
770       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
771     }
772   } else PetscCall(PetscFree(A->factorprefix));
773   PetscFunctionReturn(PETSC_SUCCESS);
774 }
775 
776 /*@C
777   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
778   for matrices created with `MatGetFactor()`
779 
780   Logically Collective
781 
782   Input Parameters:
783 + A      - the matrix
784 - prefix - the prefix to prepend to all option names for the factored matrix
785 
786   Level: developer
787 
788   Notes:
789   A hyphen (-) must NOT be given at the beginning of the prefix name.
790   The first character of all runtime options is AUTOMATICALLY the hyphen.
791 
792   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
793   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
794 
795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
796           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
797           `MatSetOptionsPrefix()`
798 @*/
799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
800 {
801   size_t len1, len2, new_len;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!A->factorprefix) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(A->factorprefix, &len1));
813   PetscCall(PetscStrlen(prefix, &len2));
814   new_len = len1 + len2 + 1;
815   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
816   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
817   PetscFunctionReturn(PETSC_SUCCESS);
818 }
819 
820 /*@C
821   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
822   matrix options in the database.
823 
824   Logically Collective
825 
826   Input Parameters:
827 + A      - the matrix
828 - prefix - the prefix to prepend to all option names
829 
830   Level: advanced
831 
832   Note:
833   A hyphen (-) must NOT be given at the beginning of the prefix name.
834   The first character of all runtime options is AUTOMATICALLY the hyphen.
835 
836 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
837 @*/
838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
842   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(PETSC_SUCCESS);
844 }
845 
846 /*@C
847   MatGetOptionsPrefix - Gets the prefix used for searching for all
848   matrix options in the database.
849 
850   Not Collective
851 
852   Input Parameter:
853 . A - the matrix
854 
855   Output Parameter:
856 . prefix - pointer to the prefix string used
857 
858   Level: advanced
859 
860   Fortran Note:
861   The user should pass in a string `prefix` of
862   sufficient length to hold the prefix.
863 
864 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
865 @*/
866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
867 {
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
870   PetscAssertPointer(prefix, 2);
871   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
872   PetscFunctionReturn(PETSC_SUCCESS);
873 }
874 
875 /*@
876   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
877 
878   Collective
879 
880   Input Parameter:
881 . A - the matrix
882 
883   Level: beginner
884 
885   Notes:
886   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
887 
888   Users can reset the preallocation to access the original memory.
889 
890   Currently only supported for  `MATAIJ` matrices.
891 
892 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
893 @*/
894 PetscErrorCode MatResetPreallocation(Mat A)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
898   PetscValidType(A, 1);
899   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
900   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
901   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
902   PetscFunctionReturn(PETSC_SUCCESS);
903 }
904 
905 /*@
906   MatSetUp - Sets up the internal matrix data structures for later use.
907 
908   Collective
909 
910   Input Parameter:
911 . A - the matrix
912 
913   Level: intermediate
914 
915   Notes:
916   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
917   setting values in the matrix.
918 
919   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
920 
921 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
922 @*/
923 PetscErrorCode MatSetUp(Mat A)
924 {
925   PetscFunctionBegin;
926   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
927   if (!((PetscObject)A)->type_name) {
928     PetscMPIInt size;
929 
930     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
931     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
932   }
933   if (!A->preallocated) PetscTryTypeMethod(A, setup);
934   PetscCall(PetscLayoutSetUp(A->rmap));
935   PetscCall(PetscLayoutSetUp(A->cmap));
936   A->preallocated = PETSC_TRUE;
937   PetscFunctionReturn(PETSC_SUCCESS);
938 }
939 
940 #if defined(PETSC_HAVE_SAWS)
941   #include <petscviewersaws.h>
942 #endif
943 
944 /*
945    If threadsafety is on extraneous matrices may be printed
946 
947    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
948 */
949 #if !defined(PETSC_HAVE_THREADSAFETY)
950 static PetscInt insidematview = 0;
951 #endif
952 
953 /*@C
954   MatViewFromOptions - View properties of the matrix based on options set in the options database
955 
956   Collective
957 
958   Input Parameters:
959 + A    - the matrix
960 . obj  - optional additional object that provides the options prefix to use
961 - name - command line option
962 
963   Options Database Key:
964 . -mat_view [viewertype]:... - the viewer and its options
965 
966   Level: intermediate
967 
968   Note:
969 .vb
970     If no value is provided ascii:stdout is used
971        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
972                                                   for example ascii::ascii_info prints just the information about the object not all details
973                                                   unless :append is given filename opens in write mode, overwriting what was already there
974        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
975        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
976        socket[:port]                             defaults to the standard output port
977        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
978 .ve
979 
980 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
981 @*/
982 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
983 {
984   PetscFunctionBegin;
985   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
986 #if !defined(PETSC_HAVE_THREADSAFETY)
987   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
988 #endif
989   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
990   PetscFunctionReturn(PETSC_SUCCESS);
991 }
992 
993 /*@C
994   MatView - display information about a matrix in a variety ways
995 
996   Collective
997 
998   Input Parameters:
999 + mat    - the matrix
1000 - viewer - visualization context
1001 
1002   Options Database Keys:
1003 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1004 . -mat_view ::ascii_info_detail    - Prints more detailed info
1005 . -mat_view                        - Prints matrix in ASCII format
1006 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1007 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1008 . -display <name>                  - Sets display name (default is host)
1009 . -draw_pause <sec>                - Sets number of seconds to pause after display
1010 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1011 . -viewer_socket_machine <machine> - -
1012 . -viewer_socket_port <port>       - -
1013 . -mat_view binary                 - save matrix to file in binary format
1014 - -viewer_binary_filename <name>   - -
1015 
1016   Level: beginner
1017 
1018   Notes:
1019   The available visualization contexts include
1020 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1021 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1022 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1023 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1024 
1025   The user can open alternative visualization contexts with
1026 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1027 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1028   specified file; corresponding input uses `MatLoad()`
1029 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1030   an X window display
1031 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1032   Currently only the `MATSEQDENSE` and `MATAIJ`
1033   matrix types support the Socket viewer.
1034 
1035   The user can call `PetscViewerPushFormat()` to specify the output
1036   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1037   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1038 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1039 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1040 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1041 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1042   format common among all matrix types
1043 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1044   format (which is in many cases the same as the default)
1045 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1046   size and structure (not the matrix entries)
1047 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1048   the matrix structure
1049 
1050   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1051   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1052 
1053   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1054 
1055   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1056   viewer is used.
1057 
1058   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1059   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1060 
1061   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1062   and then use the following mouse functions.
1063 .vb
1064   left mouse: zoom in
1065   middle mouse: zoom out
1066   right mouse: continue with the simulation
1067 .ve
1068 
1069 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1070           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1071 @*/
1072 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1073 {
1074   PetscInt          rows, cols, rbs, cbs;
1075   PetscBool         isascii, isstring, issaws;
1076   PetscViewerFormat format;
1077   PetscMPIInt       size;
1078 
1079   PetscFunctionBegin;
1080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1081   PetscValidType(mat, 1);
1082   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1083   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1084   PetscCheckSameComm(mat, 1, viewer, 2);
1085 
1086   PetscCall(PetscViewerGetFormat(viewer, &format));
1087   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1088   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1089 
1090 #if !defined(PETSC_HAVE_THREADSAFETY)
1091   insidematview++;
1092 #endif
1093   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1094   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1096   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1097 
1098   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1099   if (isascii) {
1100     if (!mat->preallocated) {
1101       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1102 #if !defined(PETSC_HAVE_THREADSAFETY)
1103       insidematview--;
1104 #endif
1105       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1106       PetscFunctionReturn(PETSC_SUCCESS);
1107     }
1108     if (!mat->assembled) {
1109       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1110 #if !defined(PETSC_HAVE_THREADSAFETY)
1111       insidematview--;
1112 #endif
1113       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1114       PetscFunctionReturn(PETSC_SUCCESS);
1115     }
1116     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1117     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1118       MatNullSpace nullsp, transnullsp;
1119 
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatGetSize(mat, &rows, &cols));
1122       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1123       if (rbs != 1 || cbs != 1) {
1124         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1125         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1126       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1127       if (mat->factortype) {
1128         MatSolverType solver;
1129         PetscCall(MatFactorGetSolverType(mat, &solver));
1130         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1131       }
1132       if (mat->ops->getinfo) {
1133         MatInfo info;
1134         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1135         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1136         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1137       }
1138       PetscCall(MatGetNullSpace(mat, &nullsp));
1139       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1140       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1141       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1142       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1143       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1144       PetscCall(PetscViewerASCIIPushTab(viewer));
1145       PetscCall(MatProductView(mat, viewer));
1146       PetscCall(PetscViewerASCIIPopTab(viewer));
1147     }
1148   } else if (issaws) {
1149 #if defined(PETSC_HAVE_SAWS)
1150     PetscMPIInt rank;
1151 
1152     PetscCall(PetscObjectName((PetscObject)mat));
1153     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1154     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1155 #endif
1156   } else if (isstring) {
1157     const char *type;
1158     PetscCall(MatGetType(mat, &type));
1159     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1160     PetscTryTypeMethod(mat, view, viewer);
1161   }
1162   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1163     PetscCall(PetscViewerASCIIPushTab(viewer));
1164     PetscUseTypeMethod(mat, viewnative, viewer);
1165     PetscCall(PetscViewerASCIIPopTab(viewer));
1166   } else if (mat->ops->view) {
1167     PetscCall(PetscViewerASCIIPushTab(viewer));
1168     PetscUseTypeMethod(mat, view, viewer);
1169     PetscCall(PetscViewerASCIIPopTab(viewer));
1170   }
1171   if (isascii) {
1172     PetscCall(PetscViewerGetFormat(viewer, &format));
1173     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1174   }
1175   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1176 #if !defined(PETSC_HAVE_THREADSAFETY)
1177   insidematview--;
1178 #endif
1179   PetscFunctionReturn(PETSC_SUCCESS);
1180 }
1181 
1182 #if defined(PETSC_USE_DEBUG)
1183   #include <../src/sys/totalview/tv_data_display.h>
1184 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1185 {
1186   TV_add_row("Local rows", "int", &mat->rmap->n);
1187   TV_add_row("Local columns", "int", &mat->cmap->n);
1188   TV_add_row("Global rows", "int", &mat->rmap->N);
1189   TV_add_row("Global columns", "int", &mat->cmap->N);
1190   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1191   return TV_format_OK;
1192 }
1193 #endif
1194 
1195 /*@C
1196   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1197   with `MatView()`.  The matrix format is determined from the options database.
1198   Generates a parallel MPI matrix if the communicator has more than one
1199   processor.  The default matrix type is `MATAIJ`.
1200 
1201   Collective
1202 
1203   Input Parameters:
1204 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1205             or some related function before a call to `MatLoad()`
1206 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1207 
1208   Options Database Key:
1209 . -matload_block_size <bs> - set block size
1210 
1211   Level: beginner
1212 
1213   Notes:
1214   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1215   `Mat` before calling this routine if you wish to set it from the options database.
1216 
1217   `MatLoad()` automatically loads into the options database any options
1218   given in the file filename.info where filename is the name of the file
1219   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1220   file will be ignored if you use the -viewer_binary_skip_info option.
1221 
1222   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1223   sets the default matrix type AIJ and sets the local and global sizes.
1224   If type and/or size is already set, then the same are used.
1225 
1226   In parallel, each processor can load a subset of rows (or the
1227   entire matrix).  This routine is especially useful when a large
1228   matrix is stored on disk and only part of it is desired on each
1229   processor.  For example, a parallel solver may access only some of
1230   the rows from each processor.  The algorithm used here reads
1231   relatively small blocks of data rather than reading the entire
1232   matrix and then subsetting it.
1233 
1234   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1235   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1236   or the sequence like
1237 .vb
1238     `PetscViewer` v;
1239     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1240     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1241     `PetscViewerSetFromOptions`(v);
1242     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1243     `PetscViewerFileSetName`(v,"datafile");
1244 .ve
1245   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1246 $ -viewer_type {binary, hdf5}
1247 
1248   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1249   and src/mat/tutorials/ex10.c with the second approach.
1250 
1251   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1252   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1253   Multiple objects, both matrices and vectors, can be stored within the same file.
1254   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1255 
1256   Most users should not need to know the details of the binary storage
1257   format, since `MatLoad()` and `MatView()` completely hide these details.
1258   But for anyone who is interested, the standard binary matrix storage
1259   format is
1260 
1261 .vb
1262     PetscInt    MAT_FILE_CLASSID
1263     PetscInt    number of rows
1264     PetscInt    number of columns
1265     PetscInt    total number of nonzeros
1266     PetscInt    *number nonzeros in each row
1267     PetscInt    *column indices of all nonzeros (starting index is zero)
1268     PetscScalar *values of all nonzeros
1269 .ve
1270   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1271   stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1272   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1273 
1274   PETSc automatically does the byte swapping for
1275   machines that store the bytes reversed. Thus if you write your own binary
1276   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1277   and `PetscBinaryWrite()` to see how this may be done.
1278 
1279   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1280   Each processor's chunk is loaded independently by its owning MPI process.
1281   Multiple objects, both matrices and vectors, can be stored within the same file.
1282   They are looked up by their PetscObject name.
1283 
1284   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1285   by default the same structure and naming of the AIJ arrays and column count
1286   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1287 $    save example.mat A b -v7.3
1288   can be directly read by this routine (see Reference 1 for details).
1289 
1290   Depending on your MATLAB version, this format might be a default,
1291   otherwise you can set it as default in Preferences.
1292 
1293   Unless -nocompression flag is used to save the file in MATLAB,
1294   PETSc must be configured with ZLIB package.
1295 
1296   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1297 
1298   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1299 
1300   Corresponding `MatView()` is not yet implemented.
1301 
1302   The loaded matrix is actually a transpose of the original one in MATLAB,
1303   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1304   With this format, matrix is automatically transposed by PETSc,
1305   unless the matrix is marked as SPD or symmetric
1306   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1307 
1308   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1309 
1310 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1311  @*/
1312 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1313 {
1314   PetscBool flg;
1315 
1316   PetscFunctionBegin;
1317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1318   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1319 
1320   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1321 
1322   flg = PETSC_FALSE;
1323   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1324   if (flg) {
1325     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1326     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1327   }
1328   flg = PETSC_FALSE;
1329   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1330   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1331 
1332   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1333   PetscUseTypeMethod(mat, load, viewer);
1334   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1335   PetscFunctionReturn(PETSC_SUCCESS);
1336 }
1337 
1338 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1339 {
1340   Mat_Redundant *redund = *redundant;
1341 
1342   PetscFunctionBegin;
1343   if (redund) {
1344     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1345       PetscCall(ISDestroy(&redund->isrow));
1346       PetscCall(ISDestroy(&redund->iscol));
1347       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1348     } else {
1349       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1350       PetscCall(PetscFree(redund->sbuf_j));
1351       PetscCall(PetscFree(redund->sbuf_a));
1352       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1353         PetscCall(PetscFree(redund->rbuf_j[i]));
1354         PetscCall(PetscFree(redund->rbuf_a[i]));
1355       }
1356       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1357     }
1358 
1359     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1360     PetscCall(PetscFree(redund));
1361   }
1362   PetscFunctionReturn(PETSC_SUCCESS);
1363 }
1364 
1365 /*@C
1366   MatDestroy - Frees space taken by a matrix.
1367 
1368   Collective
1369 
1370   Input Parameter:
1371 . A - the matrix
1372 
1373   Level: beginner
1374 
1375   Developer Note:
1376   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1377   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1378   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1379   if changes are needed here.
1380 
1381 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1382 @*/
1383 PetscErrorCode MatDestroy(Mat *A)
1384 {
1385   PetscFunctionBegin;
1386   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1387   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1388   if (--((PetscObject)(*A))->refct > 0) {
1389     *A = NULL;
1390     PetscFunctionReturn(PETSC_SUCCESS);
1391   }
1392 
1393   /* if memory was published with SAWs then destroy it */
1394   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1395   PetscTryTypeMethod((*A), destroy);
1396 
1397   PetscCall(PetscFree((*A)->factorprefix));
1398   PetscCall(PetscFree((*A)->defaultvectype));
1399   PetscCall(PetscFree((*A)->defaultrandtype));
1400   PetscCall(PetscFree((*A)->bsizes));
1401   PetscCall(PetscFree((*A)->solvertype));
1402   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1403   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1404   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1405   PetscCall(MatProductClear(*A));
1406   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1407   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1408   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1409   PetscCall(MatDestroy(&(*A)->schur));
1410   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1411   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1412   PetscCall(PetscHeaderDestroy(A));
1413   PetscFunctionReturn(PETSC_SUCCESS);
1414 }
1415 
1416 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1417 /*@C
1418   MatSetValues - Inserts or adds a block of values into a matrix.
1419   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1420   MUST be called after all calls to `MatSetValues()` have been completed.
1421 
1422   Not Collective
1423 
1424   Input Parameters:
1425 + mat  - the matrix
1426 . v    - a logically two-dimensional array of values
1427 . m    - the number of rows
1428 . idxm - the global indices of the rows
1429 . n    - the number of columns
1430 . idxn - the global indices of the columns
1431 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1432 
1433   Level: beginner
1434 
1435   Notes:
1436   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1437 
1438   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1439   options cannot be mixed without intervening calls to the assembly
1440   routines.
1441 
1442   `MatSetValues()` uses 0-based row and column numbers in Fortran
1443   as well as in C.
1444 
1445   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1446   simply ignored. This allows easily inserting element stiffness matrices
1447   with homogeneous Dirichlet boundary conditions that you don't want represented
1448   in the matrix.
1449 
1450   Efficiency Alert:
1451   The routine `MatSetValuesBlocked()` may offer much better efficiency
1452   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1453 
1454   Developer Note:
1455   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1456   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1457 
1458 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1459           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1460 @*/
1461 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1462 {
1463   PetscFunctionBeginHot;
1464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1465   PetscValidType(mat, 1);
1466   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1467   PetscAssertPointer(idxm, 3);
1468   PetscAssertPointer(idxn, 5);
1469   MatCheckPreallocated(mat, 1);
1470 
1471   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1472   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1473 
1474   if (PetscDefined(USE_DEBUG)) {
1475     PetscInt i, j;
1476 
1477     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1478     for (i = 0; i < m; i++) {
1479       for (j = 0; j < n; j++) {
1480         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1481 #if defined(PETSC_USE_COMPLEX)
1482           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1483 #else
1484           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1485 #endif
1486       }
1487     }
1488     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1489     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1490   }
1491 
1492   if (mat->assembled) {
1493     mat->was_assembled = PETSC_TRUE;
1494     mat->assembled     = PETSC_FALSE;
1495   }
1496   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1497   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1498   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1499   PetscFunctionReturn(PETSC_SUCCESS);
1500 }
1501 
1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1503 /*@C
1504   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1505   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1506   MUST be called after all calls to `MatSetValues()` have been completed.
1507 
1508   Not Collective
1509 
1510   Input Parameters:
1511 + mat  - the matrix
1512 . v    - a logically two-dimensional array of values
1513 . ism  - the rows to provide
1514 . isn  - the columns to provide
1515 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1516 
1517   Level: beginner
1518 
1519   Notes:
1520   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1521 
1522   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1523   options cannot be mixed without intervening calls to the assembly
1524   routines.
1525 
1526   `MatSetValues()` uses 0-based row and column numbers in Fortran
1527   as well as in C.
1528 
1529   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1530   simply ignored. This allows easily inserting element stiffness matrices
1531   with homogeneous Dirichlet boundary conditions that you don't want represented
1532   in the matrix.
1533 
1534   Efficiency Alert:
1535   The routine `MatSetValuesBlocked()` may offer much better efficiency
1536   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1537 
1538   This is currently not optimized for any particular `ISType`
1539 
1540   Developer Note:
1541   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1542   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1543 
1544 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1545           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1546 @*/
1547 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1548 {
1549   PetscInt        m, n;
1550   const PetscInt *rows, *cols;
1551 
1552   PetscFunctionBeginHot;
1553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1554   PetscCall(ISGetIndices(ism, &rows));
1555   PetscCall(ISGetIndices(isn, &cols));
1556   PetscCall(ISGetLocalSize(ism, &m));
1557   PetscCall(ISGetLocalSize(isn, &n));
1558   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1559   PetscCall(ISRestoreIndices(ism, &rows));
1560   PetscCall(ISRestoreIndices(isn, &cols));
1561   PetscFunctionReturn(PETSC_SUCCESS);
1562 }
1563 
1564 /*@
1565   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1566   values into a matrix
1567 
1568   Not Collective
1569 
1570   Input Parameters:
1571 + mat - the matrix
1572 . row - the (block) row to set
1573 - v   - a logically two-dimensional array of values
1574 
1575   Level: intermediate
1576 
1577   Notes:
1578   The values, `v`, are column-oriented (for the block version) and sorted
1579 
1580   All the nonzero values in `row` must be provided
1581 
1582   The matrix must have previously had its column indices set, likely by having been assembled.
1583 
1584   `row` must belong to this MPI process
1585 
1586 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1587           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1588 @*/
1589 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1590 {
1591   PetscInt globalrow;
1592 
1593   PetscFunctionBegin;
1594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1595   PetscValidType(mat, 1);
1596   PetscAssertPointer(v, 3);
1597   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1598   PetscCall(MatSetValuesRow(mat, globalrow, v));
1599   PetscFunctionReturn(PETSC_SUCCESS);
1600 }
1601 
1602 /*@
1603   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1604   values into a matrix
1605 
1606   Not Collective
1607 
1608   Input Parameters:
1609 + mat - the matrix
1610 . row - the (block) row to set
1611 - v   - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1612 
1613   Level: advanced
1614 
1615   Notes:
1616   The values, `v`, are column-oriented for the block version.
1617 
1618   All the nonzeros in `row` must be provided
1619 
1620   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1621 
1622   `row` must belong to this process
1623 
1624 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1625           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1626 @*/
1627 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1628 {
1629   PetscFunctionBeginHot;
1630   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1631   PetscValidType(mat, 1);
1632   MatCheckPreallocated(mat, 1);
1633   PetscAssertPointer(v, 3);
1634   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1635   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1636   mat->insertmode = INSERT_VALUES;
1637 
1638   if (mat->assembled) {
1639     mat->was_assembled = PETSC_TRUE;
1640     mat->assembled     = PETSC_FALSE;
1641   }
1642   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1643   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1644   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1645   PetscFunctionReturn(PETSC_SUCCESS);
1646 }
1647 
1648 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1649 /*@
1650   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1651   Using structured grid indexing
1652 
1653   Not Collective
1654 
1655   Input Parameters:
1656 + mat  - the matrix
1657 . m    - number of rows being entered
1658 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1659 . n    - number of columns being entered
1660 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1661 . v    - a logically two-dimensional array of values
1662 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1663 
1664   Level: beginner
1665 
1666   Notes:
1667   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1668 
1669   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1670   options cannot be mixed without intervening calls to the assembly
1671   routines.
1672 
1673   The grid coordinates are across the entire grid, not just the local portion
1674 
1675   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1676   as well as in C.
1677 
1678   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1679 
1680   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1681   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1682 
1683   The columns and rows in the stencil passed in MUST be contained within the
1684   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1685   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1686   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1687   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1688 
1689   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1690   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1691   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1692   `DM_BOUNDARY_PERIODIC` boundary type.
1693 
1694   For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1695   a single value per point) you can skip filling those indices.
1696 
1697   Inspired by the structured grid interface to the HYPRE package
1698   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1699 
1700   Efficiency Alert:
1701   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1702   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1703 
1704   Fortran Note:
1705   `idxm` and `idxn` should be declared as
1706 $     MatStencil idxm(4,m),idxn(4,n)
1707   and the values inserted using
1708 .vb
1709     idxm(MatStencil_i,1) = i
1710     idxm(MatStencil_j,1) = j
1711     idxm(MatStencil_k,1) = k
1712     idxm(MatStencil_c,1) = c
1713     etc
1714 .ve
1715 
1716 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1717           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1718 @*/
1719 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1720 {
1721   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1722   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1723   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1724 
1725   PetscFunctionBegin;
1726   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1728   PetscValidType(mat, 1);
1729   PetscAssertPointer(idxm, 3);
1730   PetscAssertPointer(idxn, 5);
1731 
1732   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1733     jdxm = buf;
1734     jdxn = buf + m;
1735   } else {
1736     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1737     jdxm = bufm;
1738     jdxn = bufn;
1739   }
1740   for (i = 0; i < m; i++) {
1741     for (j = 0; j < 3 - sdim; j++) dxm++;
1742     tmp = *dxm++ - starts[0];
1743     for (j = 0; j < dim - 1; j++) {
1744       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1745       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1746     }
1747     if (mat->stencil.noc) dxm++;
1748     jdxm[i] = tmp;
1749   }
1750   for (i = 0; i < n; i++) {
1751     for (j = 0; j < 3 - sdim; j++) dxn++;
1752     tmp = *dxn++ - starts[0];
1753     for (j = 0; j < dim - 1; j++) {
1754       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1755       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1756     }
1757     if (mat->stencil.noc) dxn++;
1758     jdxn[i] = tmp;
1759   }
1760   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1761   PetscCall(PetscFree2(bufm, bufn));
1762   PetscFunctionReturn(PETSC_SUCCESS);
1763 }
1764 
1765 /*@
1766   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1767   Using structured grid indexing
1768 
1769   Not Collective
1770 
1771   Input Parameters:
1772 + mat  - the matrix
1773 . m    - number of rows being entered
1774 . idxm - grid coordinates for matrix rows being entered
1775 . n    - number of columns being entered
1776 . idxn - grid coordinates for matrix columns being entered
1777 . v    - a logically two-dimensional array of values
1778 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1779 
1780   Level: beginner
1781 
1782   Notes:
1783   By default the values, `v`, are row-oriented and unsorted.
1784   See `MatSetOption()` for other options.
1785 
1786   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1787   options cannot be mixed without intervening calls to the assembly
1788   routines.
1789 
1790   The grid coordinates are across the entire grid, not just the local portion
1791 
1792   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1793   as well as in C.
1794 
1795   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1796 
1797   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1798   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1799 
1800   The columns and rows in the stencil passed in MUST be contained within the
1801   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1802   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1803   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1804   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1805 
1806   Negative indices may be passed in idxm and idxn, these rows and columns are
1807   simply ignored. This allows easily inserting element stiffness matrices
1808   with homogeneous Dirichlet boundary conditions that you don't want represented
1809   in the matrix.
1810 
1811   Inspired by the structured grid interface to the HYPRE package
1812   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1813 
1814   Fortran Note:
1815   `idxm` and `idxn` should be declared as
1816 $     MatStencil idxm(4,m),idxn(4,n)
1817   and the values inserted using
1818 .vb
1819     idxm(MatStencil_i,1) = i
1820     idxm(MatStencil_j,1) = j
1821     idxm(MatStencil_k,1) = k
1822    etc
1823 .ve
1824 
1825 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1826           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1827           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1828 @*/
1829 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1830 {
1831   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1832   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1833   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1834 
1835   PetscFunctionBegin;
1836   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1838   PetscValidType(mat, 1);
1839   PetscAssertPointer(idxm, 3);
1840   PetscAssertPointer(idxn, 5);
1841   PetscAssertPointer(v, 6);
1842 
1843   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1844     jdxm = buf;
1845     jdxn = buf + m;
1846   } else {
1847     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1848     jdxm = bufm;
1849     jdxn = bufn;
1850   }
1851   for (i = 0; i < m; i++) {
1852     for (j = 0; j < 3 - sdim; j++) dxm++;
1853     tmp = *dxm++ - starts[0];
1854     for (j = 0; j < sdim - 1; j++) {
1855       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1856       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1857     }
1858     dxm++;
1859     jdxm[i] = tmp;
1860   }
1861   for (i = 0; i < n; i++) {
1862     for (j = 0; j < 3 - sdim; j++) dxn++;
1863     tmp = *dxn++ - starts[0];
1864     for (j = 0; j < sdim - 1; j++) {
1865       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1866       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1867     }
1868     dxn++;
1869     jdxn[i] = tmp;
1870   }
1871   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1872   PetscCall(PetscFree2(bufm, bufn));
1873   PetscFunctionReturn(PETSC_SUCCESS);
1874 }
1875 
1876 /*@
1877   MatSetStencil - Sets the grid information for setting values into a matrix via
1878   `MatSetValuesStencil()`
1879 
1880   Not Collective
1881 
1882   Input Parameters:
1883 + mat    - the matrix
1884 . dim    - dimension of the grid 1, 2, or 3
1885 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1886 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1887 - dof    - number of degrees of freedom per node
1888 
1889   Level: beginner
1890 
1891   Notes:
1892   Inspired by the structured grid interface to the HYPRE package
1893   (www.llnl.gov/CASC/hyper)
1894 
1895   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1896   user.
1897 
1898 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1899           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1900 @*/
1901 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1902 {
1903   PetscFunctionBegin;
1904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1905   PetscAssertPointer(dims, 3);
1906   PetscAssertPointer(starts, 4);
1907 
1908   mat->stencil.dim = dim + (dof > 1);
1909   for (PetscInt i = 0; i < dim; i++) {
1910     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1911     mat->stencil.starts[i] = starts[dim - i - 1];
1912   }
1913   mat->stencil.dims[dim]   = dof;
1914   mat->stencil.starts[dim] = 0;
1915   mat->stencil.noc         = (PetscBool)(dof == 1);
1916   PetscFunctionReturn(PETSC_SUCCESS);
1917 }
1918 
1919 /*@C
1920   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1921 
1922   Not Collective
1923 
1924   Input Parameters:
1925 + mat  - the matrix
1926 . v    - a logically two-dimensional array of values
1927 . m    - the number of block rows
1928 . idxm - the global block indices
1929 . n    - the number of block columns
1930 . idxn - the global block indices
1931 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1932 
1933   Level: intermediate
1934 
1935   Notes:
1936   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1937   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1938 
1939   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1940   NOT the total number of rows/columns; for example, if the block size is 2 and
1941   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1942   The values in idxm would be 1 2; that is the first index for each block divided by
1943   the block size.
1944 
1945   You must call `MatSetBlockSize()` when constructing this matrix (before
1946   preallocating it).
1947 
1948   By default the values, `v`, are row-oriented, so the layout of
1949   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1950 
1951   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1952   options cannot be mixed without intervening calls to the assembly
1953   routines.
1954 
1955   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1956   as well as in C.
1957 
1958   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1959   simply ignored. This allows easily inserting element stiffness matrices
1960   with homogeneous Dirichlet boundary conditions that you don't want represented
1961   in the matrix.
1962 
1963   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1964   internal searching must be done to determine where to place the
1965   data in the matrix storage space.  By instead inserting blocks of
1966   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1967   reduced.
1968 
1969   Example:
1970 .vb
1971    Suppose m=n=2 and block size(bs) = 2 The array is
1972 
1973    1  2  | 3  4
1974    5  6  | 7  8
1975    - - - | - - -
1976    9  10 | 11 12
1977    13 14 | 15 16
1978 
1979    v[] should be passed in like
1980    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1981 
1982   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1983    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1984 .ve
1985 
1986 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1987 @*/
1988 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1989 {
1990   PetscFunctionBeginHot;
1991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1992   PetscValidType(mat, 1);
1993   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1994   PetscAssertPointer(idxm, 3);
1995   PetscAssertPointer(idxn, 5);
1996   MatCheckPreallocated(mat, 1);
1997   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1998   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1999   if (PetscDefined(USE_DEBUG)) {
2000     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2001     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2002   }
2003   if (PetscDefined(USE_DEBUG)) {
2004     PetscInt rbs, cbs, M, N, i;
2005     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2006     PetscCall(MatGetSize(mat, &M, &N));
2007     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
2008     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
2009   }
2010   if (mat->assembled) {
2011     mat->was_assembled = PETSC_TRUE;
2012     mat->assembled     = PETSC_FALSE;
2013   }
2014   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2015   if (mat->ops->setvaluesblocked) {
2016     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2017   } else {
2018     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2019     PetscInt i, j, bs, cbs;
2020 
2021     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2022     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2023       iidxm = buf;
2024       iidxn = buf + m * bs;
2025     } else {
2026       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2027       iidxm = bufr;
2028       iidxn = bufc;
2029     }
2030     for (i = 0; i < m; i++) {
2031       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2032     }
2033     if (m != n || bs != cbs || idxm != idxn) {
2034       for (i = 0; i < n; i++) {
2035         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2036       }
2037     } else iidxn = iidxm;
2038     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2039     PetscCall(PetscFree2(bufr, bufc));
2040   }
2041   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2042   PetscFunctionReturn(PETSC_SUCCESS);
2043 }
2044 
2045 /*@C
2046   MatGetValues - Gets a block of local values from a matrix.
2047 
2048   Not Collective; can only return values that are owned by the give process
2049 
2050   Input Parameters:
2051 + mat  - the matrix
2052 . v    - a logically two-dimensional array for storing the values
2053 . m    - the number of rows
2054 . idxm - the  global indices of the rows
2055 . n    - the number of columns
2056 - idxn - the global indices of the columns
2057 
2058   Level: advanced
2059 
2060   Notes:
2061   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2062   The values, `v`, are then returned in a row-oriented format,
2063   analogous to that used by default in `MatSetValues()`.
2064 
2065   `MatGetValues()` uses 0-based row and column numbers in
2066   Fortran as well as in C.
2067 
2068   `MatGetValues()` requires that the matrix has been assembled
2069   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2070   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2071   without intermediate matrix assembly.
2072 
2073   Negative row or column indices will be ignored and those locations in `v` will be
2074   left unchanged.
2075 
2076   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2077   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2078   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2079 
2080 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2081 @*/
2082 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2083 {
2084   PetscFunctionBegin;
2085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2086   PetscValidType(mat, 1);
2087   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2088   PetscAssertPointer(idxm, 3);
2089   PetscAssertPointer(idxn, 5);
2090   PetscAssertPointer(v, 6);
2091   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2092   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2093   MatCheckPreallocated(mat, 1);
2094 
2095   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2096   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2097   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2098   PetscFunctionReturn(PETSC_SUCCESS);
2099 }
2100 
2101 /*@C
2102   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2103   defined previously by `MatSetLocalToGlobalMapping()`
2104 
2105   Not Collective
2106 
2107   Input Parameters:
2108 + mat  - the matrix
2109 . nrow - number of rows
2110 . irow - the row local indices
2111 . ncol - number of columns
2112 - icol - the column local indices
2113 
2114   Output Parameter:
2115 . y - a logically two-dimensional array of values
2116 
2117   Level: advanced
2118 
2119   Notes:
2120   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2121 
2122   This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering,
2123   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2124   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2125   with `MatSetLocalToGlobalMapping()`.
2126 
2127   Developer Note:
2128   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2129   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2130 
2131 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2132           `MatSetValuesLocal()`, `MatGetValues()`
2133 @*/
2134 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2135 {
2136   PetscFunctionBeginHot;
2137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2138   PetscValidType(mat, 1);
2139   MatCheckPreallocated(mat, 1);
2140   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2141   PetscAssertPointer(irow, 3);
2142   PetscAssertPointer(icol, 5);
2143   if (PetscDefined(USE_DEBUG)) {
2144     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2145     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2146   }
2147   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2148   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2149   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2150   else {
2151     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2152     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2153       irowm = buf;
2154       icolm = buf + nrow;
2155     } else {
2156       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2157       irowm = bufr;
2158       icolm = bufc;
2159     }
2160     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2161     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2162     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2163     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2164     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2165     PetscCall(PetscFree2(bufr, bufc));
2166   }
2167   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2168   PetscFunctionReturn(PETSC_SUCCESS);
2169 }
2170 
2171 /*@
2172   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2173   the same size. Currently, this can only be called once and creates the given matrix.
2174 
2175   Not Collective
2176 
2177   Input Parameters:
2178 + mat  - the matrix
2179 . nb   - the number of blocks
2180 . bs   - the number of rows (and columns) in each block
2181 . rows - a concatenation of the rows for each block
2182 - v    - a concatenation of logically two-dimensional arrays of values
2183 
2184   Level: advanced
2185 
2186   Notes:
2187   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2188 
2189   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2190 
2191 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2192           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2193 @*/
2194 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2195 {
2196   PetscFunctionBegin;
2197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2198   PetscValidType(mat, 1);
2199   PetscAssertPointer(rows, 4);
2200   PetscAssertPointer(v, 5);
2201   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2202 
2203   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2204   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2205   else {
2206     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2207   }
2208   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2209   PetscFunctionReturn(PETSC_SUCCESS);
2210 }
2211 
2212 /*@
2213   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2214   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2215   using a local (per-processor) numbering.
2216 
2217   Not Collective
2218 
2219   Input Parameters:
2220 + x        - the matrix
2221 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2222 - cmapping - column mapping
2223 
2224   Level: intermediate
2225 
2226   Note:
2227   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2228 
2229 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2230 @*/
2231 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2232 {
2233   PetscFunctionBegin;
2234   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2235   PetscValidType(x, 1);
2236   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2237   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2238   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2239   else {
2240     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2241     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2242   }
2243   PetscFunctionReturn(PETSC_SUCCESS);
2244 }
2245 
2246 /*@
2247   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2248 
2249   Not Collective
2250 
2251   Input Parameter:
2252 . A - the matrix
2253 
2254   Output Parameters:
2255 + rmapping - row mapping
2256 - cmapping - column mapping
2257 
2258   Level: advanced
2259 
2260 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2261 @*/
2262 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2263 {
2264   PetscFunctionBegin;
2265   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2266   PetscValidType(A, 1);
2267   if (rmapping) {
2268     PetscAssertPointer(rmapping, 2);
2269     *rmapping = A->rmap->mapping;
2270   }
2271   if (cmapping) {
2272     PetscAssertPointer(cmapping, 3);
2273     *cmapping = A->cmap->mapping;
2274   }
2275   PetscFunctionReturn(PETSC_SUCCESS);
2276 }
2277 
2278 /*@
2279   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2280 
2281   Logically Collective
2282 
2283   Input Parameters:
2284 + A    - the matrix
2285 . rmap - row layout
2286 - cmap - column layout
2287 
2288   Level: advanced
2289 
2290   Note:
2291   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2292 
2293 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2294 @*/
2295 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2296 {
2297   PetscFunctionBegin;
2298   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2299   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2300   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2301   PetscFunctionReturn(PETSC_SUCCESS);
2302 }
2303 
2304 /*@
2305   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2306 
2307   Not Collective
2308 
2309   Input Parameter:
2310 . A - the matrix
2311 
2312   Output Parameters:
2313 + rmap - row layout
2314 - cmap - column layout
2315 
2316   Level: advanced
2317 
2318 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2319 @*/
2320 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2321 {
2322   PetscFunctionBegin;
2323   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2324   PetscValidType(A, 1);
2325   if (rmap) {
2326     PetscAssertPointer(rmap, 2);
2327     *rmap = A->rmap;
2328   }
2329   if (cmap) {
2330     PetscAssertPointer(cmap, 3);
2331     *cmap = A->cmap;
2332   }
2333   PetscFunctionReturn(PETSC_SUCCESS);
2334 }
2335 
2336 /*@C
2337   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2338   using a local numbering of the rows and columns.
2339 
2340   Not Collective
2341 
2342   Input Parameters:
2343 + mat  - the matrix
2344 . nrow - number of rows
2345 . irow - the row local indices
2346 . ncol - number of columns
2347 . icol - the column local indices
2348 . y    - a logically two-dimensional array of values
2349 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2350 
2351   Level: intermediate
2352 
2353   Notes:
2354   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2355 
2356   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2357   options cannot be mixed without intervening calls to the assembly
2358   routines.
2359 
2360   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2361   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2362 
2363   Developer Note:
2364   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2365   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2366 
2367 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2368           `MatGetValuesLocal()`
2369 @*/
2370 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2371 {
2372   PetscFunctionBeginHot;
2373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2374   PetscValidType(mat, 1);
2375   MatCheckPreallocated(mat, 1);
2376   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2377   PetscAssertPointer(irow, 3);
2378   PetscAssertPointer(icol, 5);
2379   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2380   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2381   if (PetscDefined(USE_DEBUG)) {
2382     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2383     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2384   }
2385 
2386   if (mat->assembled) {
2387     mat->was_assembled = PETSC_TRUE;
2388     mat->assembled     = PETSC_FALSE;
2389   }
2390   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2391   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2392   else {
2393     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2394     const PetscInt *irowm, *icolm;
2395 
2396     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2397       bufr  = buf;
2398       bufc  = buf + nrow;
2399       irowm = bufr;
2400       icolm = bufc;
2401     } else {
2402       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2403       irowm = bufr;
2404       icolm = bufc;
2405     }
2406     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2407     else irowm = irow;
2408     if (mat->cmap->mapping) {
2409       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2410         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2411       } else icolm = irowm;
2412     } else icolm = icol;
2413     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2414     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2415   }
2416   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2417   PetscFunctionReturn(PETSC_SUCCESS);
2418 }
2419 
2420 /*@C
2421   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2422   using a local ordering of the nodes a block at a time.
2423 
2424   Not Collective
2425 
2426   Input Parameters:
2427 + mat  - the matrix
2428 . nrow - number of rows
2429 . irow - the row local indices
2430 . ncol - number of columns
2431 . icol - the column local indices
2432 . y    - a logically two-dimensional array of values
2433 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2434 
2435   Level: intermediate
2436 
2437   Notes:
2438   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2439   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2440 
2441   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2442   options cannot be mixed without intervening calls to the assembly
2443   routines.
2444 
2445   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2446   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2447 
2448   Developer Note:
2449   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2450   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2451 
2452 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2453           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2454 @*/
2455 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2456 {
2457   PetscFunctionBeginHot;
2458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2459   PetscValidType(mat, 1);
2460   MatCheckPreallocated(mat, 1);
2461   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2462   PetscAssertPointer(irow, 3);
2463   PetscAssertPointer(icol, 5);
2464   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2465   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2466   if (PetscDefined(USE_DEBUG)) {
2467     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2468     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2469   }
2470 
2471   if (mat->assembled) {
2472     mat->was_assembled = PETSC_TRUE;
2473     mat->assembled     = PETSC_FALSE;
2474   }
2475   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2476     PetscInt irbs, rbs;
2477     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2478     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2479     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2480   }
2481   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2482     PetscInt icbs, cbs;
2483     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2484     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2485     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2486   }
2487   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2488   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2489   else {
2490     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2491     const PetscInt *irowm, *icolm;
2492 
2493     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2494       bufr  = buf;
2495       bufc  = buf + nrow;
2496       irowm = bufr;
2497       icolm = bufc;
2498     } else {
2499       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2500       irowm = bufr;
2501       icolm = bufc;
2502     }
2503     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2504     else irowm = irow;
2505     if (mat->cmap->mapping) {
2506       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2507         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2508       } else icolm = irowm;
2509     } else icolm = icol;
2510     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2511     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2512   }
2513   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2514   PetscFunctionReturn(PETSC_SUCCESS);
2515 }
2516 
2517 /*@
2518   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2519 
2520   Collective
2521 
2522   Input Parameters:
2523 + mat - the matrix
2524 - x   - the vector to be multiplied
2525 
2526   Output Parameter:
2527 . y - the result
2528 
2529   Level: developer
2530 
2531   Note:
2532   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2533   call `MatMultDiagonalBlock`(A,y,y).
2534 
2535 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2536 @*/
2537 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2538 {
2539   PetscFunctionBegin;
2540   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2541   PetscValidType(mat, 1);
2542   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2543   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2544 
2545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2547   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2548   MatCheckPreallocated(mat, 1);
2549 
2550   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2551   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2552   PetscFunctionReturn(PETSC_SUCCESS);
2553 }
2554 
2555 /*@
2556   MatMult - Computes the matrix-vector product, $y = Ax$.
2557 
2558   Neighbor-wise Collective
2559 
2560   Input Parameters:
2561 + mat - the matrix
2562 - x   - the vector to be multiplied
2563 
2564   Output Parameter:
2565 . y - the result
2566 
2567   Level: beginner
2568 
2569   Note:
2570   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2571   call `MatMult`(A,y,y).
2572 
2573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2574 @*/
2575 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2576 {
2577   PetscFunctionBegin;
2578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2579   PetscValidType(mat, 1);
2580   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2581   VecCheckAssembled(x);
2582   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2583   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2584   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2585   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2586   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2587   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2588   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2589   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2590   PetscCall(VecSetErrorIfLocked(y, 3));
2591   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2592   MatCheckPreallocated(mat, 1);
2593 
2594   PetscCall(VecLockReadPush(x));
2595   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2596   PetscUseTypeMethod(mat, mult, x, y);
2597   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2598   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2599   PetscCall(VecLockReadPop(x));
2600   PetscFunctionReturn(PETSC_SUCCESS);
2601 }
2602 
2603 /*@
2604   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2605 
2606   Neighbor-wise Collective
2607 
2608   Input Parameters:
2609 + mat - the matrix
2610 - x   - the vector to be multiplied
2611 
2612   Output Parameter:
2613 . y - the result
2614 
2615   Level: beginner
2616 
2617   Notes:
2618   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2619   call `MatMultTranspose`(A,y,y).
2620 
2621   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2622   use `MatMultHermitianTranspose()`
2623 
2624 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2625 @*/
2626 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2627 {
2628   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2629 
2630   PetscFunctionBegin;
2631   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2632   PetscValidType(mat, 1);
2633   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2634   VecCheckAssembled(x);
2635   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2636 
2637   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2638   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2639   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2640   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2641   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2642   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2643   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2644   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2645   MatCheckPreallocated(mat, 1);
2646 
2647   if (!mat->ops->multtranspose) {
2648     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2649     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2650   } else op = mat->ops->multtranspose;
2651   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2652   PetscCall(VecLockReadPush(x));
2653   PetscCall((*op)(mat, x, y));
2654   PetscCall(VecLockReadPop(x));
2655   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2656   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2657   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2658   PetscFunctionReturn(PETSC_SUCCESS);
2659 }
2660 
2661 /*@
2662   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2663 
2664   Neighbor-wise Collective
2665 
2666   Input Parameters:
2667 + mat - the matrix
2668 - x   - the vector to be multiplied
2669 
2670   Output Parameter:
2671 . y - the result
2672 
2673   Level: beginner
2674 
2675   Notes:
2676   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2677   call `MatMultHermitianTranspose`(A,y,y).
2678 
2679   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2680 
2681   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2682 
2683 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2684 @*/
2685 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2686 {
2687   PetscFunctionBegin;
2688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2689   PetscValidType(mat, 1);
2690   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2691   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2692 
2693   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2694   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2695   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2696   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2697   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2698   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2699   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2700   MatCheckPreallocated(mat, 1);
2701 
2702   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2703 #if defined(PETSC_USE_COMPLEX)
2704   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2705     PetscCall(VecLockReadPush(x));
2706     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2707     else PetscUseTypeMethod(mat, mult, x, y);
2708     PetscCall(VecLockReadPop(x));
2709   } else {
2710     Vec w;
2711     PetscCall(VecDuplicate(x, &w));
2712     PetscCall(VecCopy(x, w));
2713     PetscCall(VecConjugate(w));
2714     PetscCall(MatMultTranspose(mat, w, y));
2715     PetscCall(VecDestroy(&w));
2716     PetscCall(VecConjugate(y));
2717   }
2718   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2719 #else
2720   PetscCall(MatMultTranspose(mat, x, y));
2721 #endif
2722   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2723   PetscFunctionReturn(PETSC_SUCCESS);
2724 }
2725 
2726 /*@
2727   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2728 
2729   Neighbor-wise Collective
2730 
2731   Input Parameters:
2732 + mat - the matrix
2733 . v1  - the vector to be multiplied by `mat`
2734 - v2  - the vector to be added to the result
2735 
2736   Output Parameter:
2737 . v3 - the result
2738 
2739   Level: beginner
2740 
2741   Note:
2742   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2743   call `MatMultAdd`(A,v1,v2,v1).
2744 
2745 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2746 @*/
2747 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2748 {
2749   PetscFunctionBegin;
2750   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2751   PetscValidType(mat, 1);
2752   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2753   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2754   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2755 
2756   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2757   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2758   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2759   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2760      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2761   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2762   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2763   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2764   MatCheckPreallocated(mat, 1);
2765 
2766   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2767   PetscCall(VecLockReadPush(v1));
2768   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2769   PetscCall(VecLockReadPop(v1));
2770   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2771   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2772   PetscFunctionReturn(PETSC_SUCCESS);
2773 }
2774 
2775 /*@
2776   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2777 
2778   Neighbor-wise Collective
2779 
2780   Input Parameters:
2781 + mat - the matrix
2782 . v1  - the vector to be multiplied by the transpose of the matrix
2783 - v2  - the vector to be added to the result
2784 
2785   Output Parameter:
2786 . v3 - the result
2787 
2788   Level: beginner
2789 
2790   Note:
2791   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2792   call `MatMultTransposeAdd`(A,v1,v2,v1).
2793 
2794 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2795 @*/
2796 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2797 {
2798   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2799 
2800   PetscFunctionBegin;
2801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2802   PetscValidType(mat, 1);
2803   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2804   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2805   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2806 
2807   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2808   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2809   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2810   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2811   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2812   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2813   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2814   MatCheckPreallocated(mat, 1);
2815 
2816   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2817   PetscCall(VecLockReadPush(v1));
2818   PetscCall((*op)(mat, v1, v2, v3));
2819   PetscCall(VecLockReadPop(v1));
2820   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2821   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2822   PetscFunctionReturn(PETSC_SUCCESS);
2823 }
2824 
2825 /*@
2826   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2827 
2828   Neighbor-wise Collective
2829 
2830   Input Parameters:
2831 + mat - the matrix
2832 . v1  - the vector to be multiplied by the Hermitian transpose
2833 - v2  - the vector to be added to the result
2834 
2835   Output Parameter:
2836 . v3 - the result
2837 
2838   Level: beginner
2839 
2840   Note:
2841   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2842   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2843 
2844 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2845 @*/
2846 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2847 {
2848   PetscFunctionBegin;
2849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2850   PetscValidType(mat, 1);
2851   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2852   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2853   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2854 
2855   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2856   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2857   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2858   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2859   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2860   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2861   MatCheckPreallocated(mat, 1);
2862 
2863   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2864   PetscCall(VecLockReadPush(v1));
2865   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2866   else {
2867     Vec w, z;
2868     PetscCall(VecDuplicate(v1, &w));
2869     PetscCall(VecCopy(v1, w));
2870     PetscCall(VecConjugate(w));
2871     PetscCall(VecDuplicate(v3, &z));
2872     PetscCall(MatMultTranspose(mat, w, z));
2873     PetscCall(VecDestroy(&w));
2874     PetscCall(VecConjugate(z));
2875     if (v2 != v3) {
2876       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2877     } else {
2878       PetscCall(VecAXPY(v3, 1.0, z));
2879     }
2880     PetscCall(VecDestroy(&z));
2881   }
2882   PetscCall(VecLockReadPop(v1));
2883   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2884   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2885   PetscFunctionReturn(PETSC_SUCCESS);
2886 }
2887 
2888 /*@C
2889   MatGetFactorType - gets the type of factorization a matrix is
2890 
2891   Not Collective
2892 
2893   Input Parameter:
2894 . mat - the matrix
2895 
2896   Output Parameter:
2897 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2898 
2899   Level: intermediate
2900 
2901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2902           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2903 @*/
2904 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2905 {
2906   PetscFunctionBegin;
2907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2908   PetscValidType(mat, 1);
2909   PetscAssertPointer(t, 2);
2910   *t = mat->factortype;
2911   PetscFunctionReturn(PETSC_SUCCESS);
2912 }
2913 
2914 /*@C
2915   MatSetFactorType - sets the type of factorization a matrix is
2916 
2917   Logically Collective
2918 
2919   Input Parameters:
2920 + mat - the matrix
2921 - t   - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2922 
2923   Level: intermediate
2924 
2925 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2926           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2927 @*/
2928 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2929 {
2930   PetscFunctionBegin;
2931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2932   PetscValidType(mat, 1);
2933   mat->factortype = t;
2934   PetscFunctionReturn(PETSC_SUCCESS);
2935 }
2936 
2937 /*@C
2938   MatGetInfo - Returns information about matrix storage (number of
2939   nonzeros, memory, etc.).
2940 
2941   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2942 
2943   Input Parameters:
2944 + mat  - the matrix
2945 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2946 
2947   Output Parameter:
2948 . info - matrix information context
2949 
2950   Options Database Key:
2951 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2952 
2953   Notes:
2954   The `MatInfo` context contains a variety of matrix data, including
2955   number of nonzeros allocated and used, number of mallocs during
2956   matrix assembly, etc.  Additional information for factored matrices
2957   is provided (such as the fill ratio, number of mallocs during
2958   factorization, etc.).
2959 
2960   Example:
2961   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2962   data within the MatInfo context.  For example,
2963 .vb
2964       MatInfo info;
2965       Mat     A;
2966       double  mal, nz_a, nz_u;
2967 
2968       MatGetInfo(A, MAT_LOCAL, &info);
2969       mal  = info.mallocs;
2970       nz_a = info.nz_allocated;
2971 .ve
2972 
2973   Fortran users should declare info as a double precision
2974   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2975   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2976   a complete list of parameter names.
2977 .vb
2978       double  precision info(MAT_INFO_SIZE)
2979       double  precision mal, nz_a
2980       Mat     A
2981       integer ierr
2982 
2983       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2984       mal = info(MAT_INFO_MALLOCS)
2985       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2986 .ve
2987 
2988   Level: intermediate
2989 
2990   Developer Note:
2991   The Fortran interface is not autogenerated as the
2992   interface definition cannot be generated correctly [due to `MatInfo` argument]
2993 
2994 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2995 @*/
2996 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2997 {
2998   PetscFunctionBegin;
2999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3000   PetscValidType(mat, 1);
3001   PetscAssertPointer(info, 3);
3002   MatCheckPreallocated(mat, 1);
3003   PetscUseTypeMethod(mat, getinfo, flag, info);
3004   PetscFunctionReturn(PETSC_SUCCESS);
3005 }
3006 
3007 /*
3008    This is used by external packages where it is not easy to get the info from the actual
3009    matrix factorization.
3010 */
3011 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3012 {
3013   PetscFunctionBegin;
3014   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3015   PetscFunctionReturn(PETSC_SUCCESS);
3016 }
3017 
3018 /*@C
3019   MatLUFactor - Performs in-place LU factorization of matrix.
3020 
3021   Collective
3022 
3023   Input Parameters:
3024 + mat  - the matrix
3025 . row  - row permutation
3026 . col  - column permutation
3027 - info - options for factorization, includes
3028 .vb
3029           fill - expected fill as ratio of original fill.
3030           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3031                    Run with the option -info to determine an optimal value to use
3032 .ve
3033 
3034   Level: developer
3035 
3036   Notes:
3037   Most users should employ the `KSP` interface for linear solvers
3038   instead of working directly with matrix algebra routines such as this.
3039   See, e.g., `KSPCreate()`.
3040 
3041   This changes the state of the matrix to a factored matrix; it cannot be used
3042   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3043 
3044   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3045   when not using `KSP`.
3046 
3047   Developer Note:
3048   The Fortran interface is not autogenerated as the
3049   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3050 
3051 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3052           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3053 @*/
3054 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3055 {
3056   MatFactorInfo tinfo;
3057 
3058   PetscFunctionBegin;
3059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3060   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3061   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3062   if (info) PetscAssertPointer(info, 4);
3063   PetscValidType(mat, 1);
3064   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3065   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3066   MatCheckPreallocated(mat, 1);
3067   if (!info) {
3068     PetscCall(MatFactorInfoInitialize(&tinfo));
3069     info = &tinfo;
3070   }
3071 
3072   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3073   PetscUseTypeMethod(mat, lufactor, row, col, info);
3074   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3075   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3076   PetscFunctionReturn(PETSC_SUCCESS);
3077 }
3078 
3079 /*@C
3080   MatILUFactor - Performs in-place ILU factorization of matrix.
3081 
3082   Collective
3083 
3084   Input Parameters:
3085 + mat  - the matrix
3086 . row  - row permutation
3087 . col  - column permutation
3088 - info - structure containing
3089 .vb
3090       levels - number of levels of fill.
3091       expected fill - as ratio of original fill.
3092       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3093                 missing diagonal entries)
3094 .ve
3095 
3096   Level: developer
3097 
3098   Notes:
3099   Most users should employ the `KSP` interface for linear solvers
3100   instead of working directly with matrix algebra routines such as this.
3101   See, e.g., `KSPCreate()`.
3102 
3103   Probably really in-place only when level of fill is zero, otherwise allocates
3104   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3105   when not using `KSP`.
3106 
3107   Developer Note:
3108   The Fortran interface is not autogenerated as the
3109   interface definition cannot be generated correctly [due to MatFactorInfo]
3110 
3111 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3112 @*/
3113 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3114 {
3115   PetscFunctionBegin;
3116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3117   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3118   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3119   PetscAssertPointer(info, 4);
3120   PetscValidType(mat, 1);
3121   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3122   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3123   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3124   MatCheckPreallocated(mat, 1);
3125 
3126   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3127   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3128   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3129   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3130   PetscFunctionReturn(PETSC_SUCCESS);
3131 }
3132 
3133 /*@C
3134   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3135   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3136 
3137   Collective
3138 
3139   Input Parameters:
3140 + fact - the factor matrix obtained with `MatGetFactor()`
3141 . mat  - the matrix
3142 . row  - the row permutation
3143 . col  - the column permutation
3144 - info - options for factorization, includes
3145 .vb
3146           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3147           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3148 .ve
3149 
3150   Level: developer
3151 
3152   Notes:
3153   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3154 
3155   Most users should employ the simplified `KSP` interface for linear solvers
3156   instead of working directly with matrix algebra routines such as this.
3157   See, e.g., `KSPCreate()`.
3158 
3159   Developer Note:
3160   The Fortran interface is not autogenerated as the
3161   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3162 
3163 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3164 @*/
3165 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3166 {
3167   MatFactorInfo tinfo;
3168 
3169   PetscFunctionBegin;
3170   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3172   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3173   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3174   if (info) PetscAssertPointer(info, 5);
3175   PetscValidType(fact, 1);
3176   PetscValidType(mat, 2);
3177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3179   MatCheckPreallocated(mat, 2);
3180   if (!info) {
3181     PetscCall(MatFactorInfoInitialize(&tinfo));
3182     info = &tinfo;
3183   }
3184 
3185   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3186   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3187   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3188   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3189   PetscFunctionReturn(PETSC_SUCCESS);
3190 }
3191 
3192 /*@C
3193   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3194   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3195 
3196   Collective
3197 
3198   Input Parameters:
3199 + fact - the factor matrix obtained with `MatGetFactor()`
3200 . mat  - the matrix
3201 - info - options for factorization
3202 
3203   Level: developer
3204 
3205   Notes:
3206   See `MatLUFactor()` for in-place factorization.  See
3207   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3208 
3209   Most users should employ the `KSP` interface for linear solvers
3210   instead of working directly with matrix algebra routines such as this.
3211   See, e.g., `KSPCreate()`.
3212 
3213   Developer Note:
3214   The Fortran interface is not autogenerated as the
3215   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3216 
3217 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3218 @*/
3219 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3220 {
3221   MatFactorInfo tinfo;
3222 
3223   PetscFunctionBegin;
3224   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3226   PetscValidType(fact, 1);
3227   PetscValidType(mat, 2);
3228   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3229   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3230              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3231 
3232   MatCheckPreallocated(mat, 2);
3233   if (!info) {
3234     PetscCall(MatFactorInfoInitialize(&tinfo));
3235     info = &tinfo;
3236   }
3237 
3238   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3239   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3240   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3241   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3242   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3243   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3244   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3245   PetscFunctionReturn(PETSC_SUCCESS);
3246 }
3247 
3248 /*@C
3249   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3250   symmetric matrix.
3251 
3252   Collective
3253 
3254   Input Parameters:
3255 + mat  - the matrix
3256 . perm - row and column permutations
3257 - info - expected fill as ratio of original fill
3258 
3259   Level: developer
3260 
3261   Notes:
3262   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3263   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3264 
3265   Most users should employ the `KSP` interface for linear solvers
3266   instead of working directly with matrix algebra routines such as this.
3267   See, e.g., `KSPCreate()`.
3268 
3269   Developer Note:
3270   The Fortran interface is not autogenerated as the
3271   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3272 
3273 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3274           `MatGetOrdering()`
3275 @*/
3276 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3277 {
3278   MatFactorInfo tinfo;
3279 
3280   PetscFunctionBegin;
3281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3282   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3283   if (info) PetscAssertPointer(info, 3);
3284   PetscValidType(mat, 1);
3285   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3286   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3287   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3288   MatCheckPreallocated(mat, 1);
3289   if (!info) {
3290     PetscCall(MatFactorInfoInitialize(&tinfo));
3291     info = &tinfo;
3292   }
3293 
3294   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3295   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3296   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3297   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3298   PetscFunctionReturn(PETSC_SUCCESS);
3299 }
3300 
3301 /*@C
3302   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3303   of a symmetric matrix.
3304 
3305   Collective
3306 
3307   Input Parameters:
3308 + fact - the factor matrix obtained with `MatGetFactor()`
3309 . mat  - the matrix
3310 . perm - row and column permutations
3311 - info - options for factorization, includes
3312 .vb
3313           fill - expected fill as ratio of original fill.
3314           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3315                    Run with the option -info to determine an optimal value to use
3316 .ve
3317 
3318   Level: developer
3319 
3320   Notes:
3321   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3322   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3323 
3324   Most users should employ the `KSP` interface for linear solvers
3325   instead of working directly with matrix algebra routines such as this.
3326   See, e.g., `KSPCreate()`.
3327 
3328   Developer Note:
3329   The Fortran interface is not autogenerated as the
3330   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3331 
3332 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3333           `MatGetOrdering()`
3334 @*/
3335 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3336 {
3337   MatFactorInfo tinfo;
3338 
3339   PetscFunctionBegin;
3340   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3342   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3343   if (info) PetscAssertPointer(info, 4);
3344   PetscValidType(fact, 1);
3345   PetscValidType(mat, 2);
3346   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3347   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3348   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3349   MatCheckPreallocated(mat, 2);
3350   if (!info) {
3351     PetscCall(MatFactorInfoInitialize(&tinfo));
3352     info = &tinfo;
3353   }
3354 
3355   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3356   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3357   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3358   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3359   PetscFunctionReturn(PETSC_SUCCESS);
3360 }
3361 
3362 /*@C
3363   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3364   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3365   `MatCholeskyFactorSymbolic()`.
3366 
3367   Collective
3368 
3369   Input Parameters:
3370 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3371 . mat  - the initial matrix that is to be factored
3372 - info - options for factorization
3373 
3374   Level: developer
3375 
3376   Note:
3377   Most users should employ the `KSP` interface for linear solvers
3378   instead of working directly with matrix algebra routines such as this.
3379   See, e.g., `KSPCreate()`.
3380 
3381   Developer Note:
3382   The Fortran interface is not autogenerated as the
3383   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3384 
3385 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3386 @*/
3387 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3388 {
3389   MatFactorInfo tinfo;
3390 
3391   PetscFunctionBegin;
3392   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3394   PetscValidType(fact, 1);
3395   PetscValidType(mat, 2);
3396   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3397   PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3398              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3399   MatCheckPreallocated(mat, 2);
3400   if (!info) {
3401     PetscCall(MatFactorInfoInitialize(&tinfo));
3402     info = &tinfo;
3403   }
3404 
3405   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3406   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3407   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3408   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3409   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3410   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3411   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3412   PetscFunctionReturn(PETSC_SUCCESS);
3413 }
3414 
3415 /*@
3416   MatQRFactor - Performs in-place QR factorization of matrix.
3417 
3418   Collective
3419 
3420   Input Parameters:
3421 + mat  - the matrix
3422 . col  - column permutation
3423 - info - options for factorization, includes
3424 .vb
3425           fill - expected fill as ratio of original fill.
3426           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3427                    Run with the option -info to determine an optimal value to use
3428 .ve
3429 
3430   Level: developer
3431 
3432   Notes:
3433   Most users should employ the `KSP` interface for linear solvers
3434   instead of working directly with matrix algebra routines such as this.
3435   See, e.g., `KSPCreate()`.
3436 
3437   This changes the state of the matrix to a factored matrix; it cannot be used
3438   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3439 
3440   Developer Note:
3441   The Fortran interface is not autogenerated as the
3442   interface definition cannot be generated correctly [due to MatFactorInfo]
3443 
3444 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3445           `MatSetUnfactored()`
3446 @*/
3447 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3448 {
3449   PetscFunctionBegin;
3450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3451   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3452   if (info) PetscAssertPointer(info, 3);
3453   PetscValidType(mat, 1);
3454   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3455   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3456   MatCheckPreallocated(mat, 1);
3457   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3458   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3459   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3460   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3461   PetscFunctionReturn(PETSC_SUCCESS);
3462 }
3463 
3464 /*@
3465   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3466   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3467 
3468   Collective
3469 
3470   Input Parameters:
3471 + fact - the factor matrix obtained with `MatGetFactor()`
3472 . mat  - the matrix
3473 . col  - column permutation
3474 - info - options for factorization, includes
3475 .vb
3476           fill - expected fill as ratio of original fill.
3477           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3478                    Run with the option -info to determine an optimal value to use
3479 .ve
3480 
3481   Level: developer
3482 
3483   Note:
3484   Most users should employ the `KSP` interface for linear solvers
3485   instead of working directly with matrix algebra routines such as this.
3486   See, e.g., `KSPCreate()`.
3487 
3488   Developer Note:
3489   The Fortran interface is not autogenerated as the
3490   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3491 
3492 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3493 @*/
3494 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3495 {
3496   MatFactorInfo tinfo;
3497 
3498   PetscFunctionBegin;
3499   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3500   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3501   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3502   if (info) PetscAssertPointer(info, 4);
3503   PetscValidType(fact, 1);
3504   PetscValidType(mat, 2);
3505   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3506   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3507   MatCheckPreallocated(mat, 2);
3508   if (!info) {
3509     PetscCall(MatFactorInfoInitialize(&tinfo));
3510     info = &tinfo;
3511   }
3512 
3513   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3514   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3515   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3516   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3517   PetscFunctionReturn(PETSC_SUCCESS);
3518 }
3519 
3520 /*@
3521   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3522   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3523 
3524   Collective
3525 
3526   Input Parameters:
3527 + fact - the factor matrix obtained with `MatGetFactor()`
3528 . mat  - the matrix
3529 - info - options for factorization
3530 
3531   Level: developer
3532 
3533   Notes:
3534   See `MatQRFactor()` for in-place factorization.
3535 
3536   Most users should employ the `KSP` interface for linear solvers
3537   instead of working directly with matrix algebra routines such as this.
3538   See, e.g., `KSPCreate()`.
3539 
3540   Developer Note:
3541   The Fortran interface is not autogenerated as the
3542   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3543 
3544 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3545 @*/
3546 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3547 {
3548   MatFactorInfo tinfo;
3549 
3550   PetscFunctionBegin;
3551   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3553   PetscValidType(fact, 1);
3554   PetscValidType(mat, 2);
3555   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3556   PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT,
3557              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3558 
3559   MatCheckPreallocated(mat, 2);
3560   if (!info) {
3561     PetscCall(MatFactorInfoInitialize(&tinfo));
3562     info = &tinfo;
3563   }
3564 
3565   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3566   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3567   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3568   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3569   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3570   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3571   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3572   PetscFunctionReturn(PETSC_SUCCESS);
3573 }
3574 
3575 /*@
3576   MatSolve - Solves $A x = b$, given a factored matrix.
3577 
3578   Neighbor-wise Collective
3579 
3580   Input Parameters:
3581 + mat - the factored matrix
3582 - b   - the right-hand-side vector
3583 
3584   Output Parameter:
3585 . x - the result vector
3586 
3587   Level: developer
3588 
3589   Notes:
3590   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3591   call `MatSolve`(A,x,x).
3592 
3593   Most users should employ the `KSP` interface for linear solvers
3594   instead of working directly with matrix algebra routines such as this.
3595   See, e.g., `KSPCreate()`.
3596 
3597 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3598 @*/
3599 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3600 {
3601   PetscFunctionBegin;
3602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3603   PetscValidType(mat, 1);
3604   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3605   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3606   PetscCheckSameComm(mat, 1, b, 2);
3607   PetscCheckSameComm(mat, 1, x, 3);
3608   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3609   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3610   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3611   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3612   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3613   MatCheckPreallocated(mat, 1);
3614 
3615   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3616   if (mat->factorerrortype) {
3617     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3618     PetscCall(VecSetInf(x));
3619   } else PetscUseTypeMethod(mat, solve, b, x);
3620   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3621   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3622   PetscFunctionReturn(PETSC_SUCCESS);
3623 }
3624 
3625 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3626 {
3627   Vec      b, x;
3628   PetscInt N, i;
3629   PetscErrorCode (*f)(Mat, Vec, Vec);
3630   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3631 
3632   PetscFunctionBegin;
3633   if (A->factorerrortype) {
3634     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3635     PetscCall(MatSetInf(X));
3636     PetscFunctionReturn(PETSC_SUCCESS);
3637   }
3638   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3639   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3640   PetscCall(MatBoundToCPU(A, &Abound));
3641   if (!Abound) {
3642     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3643     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3644   }
3645 #if PetscDefined(HAVE_CUDA)
3646   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3647   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3648 #elif PetscDefined(HAVE_HIP)
3649   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3650   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3651 #endif
3652   PetscCall(MatGetSize(B, NULL, &N));
3653   for (i = 0; i < N; i++) {
3654     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3655     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3656     PetscCall((*f)(A, b, x));
3657     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3658     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3659   }
3660   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3661   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3662   PetscFunctionReturn(PETSC_SUCCESS);
3663 }
3664 
3665 /*@
3666   MatMatSolve - Solves $A X = B$, given a factored matrix.
3667 
3668   Neighbor-wise Collective
3669 
3670   Input Parameters:
3671 + A - the factored matrix
3672 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3673 
3674   Output Parameter:
3675 . X - the result matrix (dense matrix)
3676 
3677   Level: developer
3678 
3679   Note:
3680   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3681   otherwise, `B` and `X` cannot be the same.
3682 
3683 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3684 @*/
3685 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3686 {
3687   PetscFunctionBegin;
3688   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3689   PetscValidType(A, 1);
3690   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3691   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3692   PetscCheckSameComm(A, 1, B, 2);
3693   PetscCheckSameComm(A, 1, X, 3);
3694   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3695   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3696   PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3697   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3698   MatCheckPreallocated(A, 1);
3699 
3700   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3701   if (!A->ops->matsolve) {
3702     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3703     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3704   } else PetscUseTypeMethod(A, matsolve, B, X);
3705   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3706   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3707   PetscFunctionReturn(PETSC_SUCCESS);
3708 }
3709 
3710 /*@
3711   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3712 
3713   Neighbor-wise Collective
3714 
3715   Input Parameters:
3716 + A - the factored matrix
3717 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3718 
3719   Output Parameter:
3720 . X - the result matrix (dense matrix)
3721 
3722   Level: developer
3723 
3724   Note:
3725   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3726   call `MatMatSolveTranspose`(A,X,X).
3727 
3728 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3729 @*/
3730 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3731 {
3732   PetscFunctionBegin;
3733   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3734   PetscValidType(A, 1);
3735   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3736   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3737   PetscCheckSameComm(A, 1, B, 2);
3738   PetscCheckSameComm(A, 1, X, 3);
3739   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3740   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3741   PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N);
3742   PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n);
3743   PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3744   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3745   MatCheckPreallocated(A, 1);
3746 
3747   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3748   if (!A->ops->matsolvetranspose) {
3749     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3750     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3751   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3752   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3753   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3754   PetscFunctionReturn(PETSC_SUCCESS);
3755 }
3756 
3757 /*@
3758   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3759 
3760   Neighbor-wise Collective
3761 
3762   Input Parameters:
3763 + A  - the factored matrix
3764 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3765 
3766   Output Parameter:
3767 . X - the result matrix (dense matrix)
3768 
3769   Level: developer
3770 
3771   Note:
3772   For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create `Bt` in sparse compressed row
3773   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3774 
3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3776 @*/
3777 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3778 {
3779   PetscFunctionBegin;
3780   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3781   PetscValidType(A, 1);
3782   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3783   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3784   PetscCheckSameComm(A, 1, Bt, 2);
3785   PetscCheckSameComm(A, 1, X, 3);
3786 
3787   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3788   PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N);
3789   PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N);
3790   PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix");
3791   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3792   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3793   MatCheckPreallocated(A, 1);
3794 
3795   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3796   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3797   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3798   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3799   PetscFunctionReturn(PETSC_SUCCESS);
3800 }
3801 
3802 /*@
3803   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3804   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3805 
3806   Neighbor-wise Collective
3807 
3808   Input Parameters:
3809 + mat - the factored matrix
3810 - b   - the right-hand-side vector
3811 
3812   Output Parameter:
3813 . x - the result vector
3814 
3815   Level: developer
3816 
3817   Notes:
3818   `MatSolve()` should be used for most applications, as it performs
3819   a forward solve followed by a backward solve.
3820 
3821   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3822   call `MatForwardSolve`(A,x,x).
3823 
3824   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3825   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3826   `MatForwardSolve()` solves $U^T*D y = b$, and
3827   `MatBackwardSolve()` solves $U x = y$.
3828   Thus they do not provide a symmetric preconditioner.
3829 
3830 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3831 @*/
3832 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3833 {
3834   PetscFunctionBegin;
3835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3836   PetscValidType(mat, 1);
3837   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3838   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3839   PetscCheckSameComm(mat, 1, b, 2);
3840   PetscCheckSameComm(mat, 1, x, 3);
3841   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3842   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3843   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3844   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3845   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3846   MatCheckPreallocated(mat, 1);
3847 
3848   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3849   PetscUseTypeMethod(mat, forwardsolve, b, x);
3850   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3851   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3852   PetscFunctionReturn(PETSC_SUCCESS);
3853 }
3854 
3855 /*@
3856   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3857   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3858 
3859   Neighbor-wise Collective
3860 
3861   Input Parameters:
3862 + mat - the factored matrix
3863 - b   - the right-hand-side vector
3864 
3865   Output Parameter:
3866 . x - the result vector
3867 
3868   Level: developer
3869 
3870   Notes:
3871   `MatSolve()` should be used for most applications, as it performs
3872   a forward solve followed by a backward solve.
3873 
3874   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3875   call `MatBackwardSolve`(A,x,x).
3876 
3877   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3878   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3879   `MatForwardSolve()` solves $U^T*D y = b$, and
3880   `MatBackwardSolve()` solves $U x = y$.
3881   Thus they do not provide a symmetric preconditioner.
3882 
3883 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3884 @*/
3885 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3886 {
3887   PetscFunctionBegin;
3888   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3889   PetscValidType(mat, 1);
3890   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3891   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3892   PetscCheckSameComm(mat, 1, b, 2);
3893   PetscCheckSameComm(mat, 1, x, 3);
3894   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3895   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3896   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3897   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3898   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3899   MatCheckPreallocated(mat, 1);
3900 
3901   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3902   PetscUseTypeMethod(mat, backwardsolve, b, x);
3903   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3904   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3905   PetscFunctionReturn(PETSC_SUCCESS);
3906 }
3907 
3908 /*@
3909   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3910 
3911   Neighbor-wise Collective
3912 
3913   Input Parameters:
3914 + mat - the factored matrix
3915 . b   - the right-hand-side vector
3916 - y   - the vector to be added to
3917 
3918   Output Parameter:
3919 . x - the result vector
3920 
3921   Level: developer
3922 
3923   Note:
3924   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3925   call `MatSolveAdd`(A,x,y,x).
3926 
3927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3928 @*/
3929 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3930 {
3931   PetscScalar one = 1.0;
3932   Vec         tmp;
3933 
3934   PetscFunctionBegin;
3935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3936   PetscValidType(mat, 1);
3937   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3938   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3939   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3940   PetscCheckSameComm(mat, 1, b, 2);
3941   PetscCheckSameComm(mat, 1, y, 3);
3942   PetscCheckSameComm(mat, 1, x, 4);
3943   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3944   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3945   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3946   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
3947   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3948   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
3949   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3950   MatCheckPreallocated(mat, 1);
3951 
3952   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3953   if (mat->factorerrortype) {
3954     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3955     PetscCall(VecSetInf(x));
3956   } else if (mat->ops->solveadd) {
3957     PetscUseTypeMethod(mat, solveadd, b, y, x);
3958   } else {
3959     /* do the solve then the add manually */
3960     if (x != y) {
3961       PetscCall(MatSolve(mat, b, x));
3962       PetscCall(VecAXPY(x, one, y));
3963     } else {
3964       PetscCall(VecDuplicate(x, &tmp));
3965       PetscCall(VecCopy(x, tmp));
3966       PetscCall(MatSolve(mat, b, x));
3967       PetscCall(VecAXPY(x, one, tmp));
3968       PetscCall(VecDestroy(&tmp));
3969     }
3970   }
3971   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3972   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3973   PetscFunctionReturn(PETSC_SUCCESS);
3974 }
3975 
3976 /*@
3977   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3978 
3979   Neighbor-wise Collective
3980 
3981   Input Parameters:
3982 + mat - the factored matrix
3983 - b   - the right-hand-side vector
3984 
3985   Output Parameter:
3986 . x - the result vector
3987 
3988   Level: developer
3989 
3990   Notes:
3991   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3992   call `MatSolveTranspose`(A,x,x).
3993 
3994   Most users should employ the `KSP` interface for linear solvers
3995   instead of working directly with matrix algebra routines such as this.
3996   See, e.g., `KSPCreate()`.
3997 
3998 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3999 @*/
4000 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4001 {
4002   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4003 
4004   PetscFunctionBegin;
4005   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4006   PetscValidType(mat, 1);
4007   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4008   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4009   PetscCheckSameComm(mat, 1, b, 2);
4010   PetscCheckSameComm(mat, 1, x, 3);
4011   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4012   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4013   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4014   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4015   MatCheckPreallocated(mat, 1);
4016   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4017   if (mat->factorerrortype) {
4018     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4019     PetscCall(VecSetInf(x));
4020   } else {
4021     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4022     PetscCall((*f)(mat, b, x));
4023   }
4024   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4025   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4026   PetscFunctionReturn(PETSC_SUCCESS);
4027 }
4028 
4029 /*@
4030   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4031   factored matrix.
4032 
4033   Neighbor-wise Collective
4034 
4035   Input Parameters:
4036 + mat - the factored matrix
4037 . b   - the right-hand-side vector
4038 - y   - the vector to be added to
4039 
4040   Output Parameter:
4041 . x - the result vector
4042 
4043   Level: developer
4044 
4045   Note:
4046   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4047   call `MatSolveTransposeAdd`(A,x,y,x).
4048 
4049 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4050 @*/
4051 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4052 {
4053   PetscScalar one = 1.0;
4054   Vec         tmp;
4055   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4056 
4057   PetscFunctionBegin;
4058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4059   PetscValidType(mat, 1);
4060   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4061   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4062   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4063   PetscCheckSameComm(mat, 1, b, 2);
4064   PetscCheckSameComm(mat, 1, y, 3);
4065   PetscCheckSameComm(mat, 1, x, 4);
4066   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4067   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4068   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4069   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
4070   PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n);
4071   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4072   MatCheckPreallocated(mat, 1);
4073 
4074   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4075   if (mat->factorerrortype) {
4076     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4077     PetscCall(VecSetInf(x));
4078   } else if (f) {
4079     PetscCall((*f)(mat, b, y, x));
4080   } else {
4081     /* do the solve then the add manually */
4082     if (x != y) {
4083       PetscCall(MatSolveTranspose(mat, b, x));
4084       PetscCall(VecAXPY(x, one, y));
4085     } else {
4086       PetscCall(VecDuplicate(x, &tmp));
4087       PetscCall(VecCopy(x, tmp));
4088       PetscCall(MatSolveTranspose(mat, b, x));
4089       PetscCall(VecAXPY(x, one, tmp));
4090       PetscCall(VecDestroy(&tmp));
4091     }
4092   }
4093   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4094   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4095   PetscFunctionReturn(PETSC_SUCCESS);
4096 }
4097 
4098 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4099 /*@
4100   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4101 
4102   Neighbor-wise Collective
4103 
4104   Input Parameters:
4105 + mat   - the matrix
4106 . b     - the right hand side
4107 . omega - the relaxation factor
4108 . flag  - flag indicating the type of SOR (see below)
4109 . shift - diagonal shift
4110 . its   - the number of iterations
4111 - lits  - the number of local iterations
4112 
4113   Output Parameter:
4114 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4115 
4116   SOR Flags:
4117 +     `SOR_FORWARD_SWEEP` - forward SOR
4118 .     `SOR_BACKWARD_SWEEP` - backward SOR
4119 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4120 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4121 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4122 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4123 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4124 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4125   upper/lower triangular part of matrix to
4126   vector (with omega)
4127 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4128 
4129   Level: developer
4130 
4131   Notes:
4132   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4133   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4134   on each processor.
4135 
4136   Application programmers will not generally use `MatSOR()` directly,
4137   but instead will employ the `KSP`/`PC` interface.
4138 
4139   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4140 
4141   Most users should employ the `KSP` interface for linear solvers
4142   instead of working directly with matrix algebra routines such as this.
4143   See, e.g., `KSPCreate()`.
4144 
4145   Vectors `x` and `b` CANNOT be the same
4146 
4147   The flags are implemented as bitwise inclusive or operations.
4148   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4149   to specify a zero initial guess for SSOR.
4150 
4151   Developer Note:
4152   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4153 
4154 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4155 @*/
4156 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4157 {
4158   PetscFunctionBegin;
4159   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4160   PetscValidType(mat, 1);
4161   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4162   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4163   PetscCheckSameComm(mat, 1, b, 2);
4164   PetscCheckSameComm(mat, 1, x, 8);
4165   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4166   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4167   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
4168   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
4169   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
4170   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4171   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4172   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4173 
4174   MatCheckPreallocated(mat, 1);
4175   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4176   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4177   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4178   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4179   PetscFunctionReturn(PETSC_SUCCESS);
4180 }
4181 
4182 /*
4183       Default matrix copy routine.
4184 */
4185 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4186 {
4187   PetscInt           i, rstart = 0, rend = 0, nz;
4188   const PetscInt    *cwork;
4189   const PetscScalar *vwork;
4190 
4191   PetscFunctionBegin;
4192   if (B->assembled) PetscCall(MatZeroEntries(B));
4193   if (str == SAME_NONZERO_PATTERN) {
4194     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4195     for (i = rstart; i < rend; i++) {
4196       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4197       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4198       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4199     }
4200   } else {
4201     PetscCall(MatAYPX(B, 0.0, A, str));
4202   }
4203   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4204   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4205   PetscFunctionReturn(PETSC_SUCCESS);
4206 }
4207 
4208 /*@
4209   MatCopy - Copies a matrix to another matrix.
4210 
4211   Collective
4212 
4213   Input Parameters:
4214 + A   - the matrix
4215 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4216 
4217   Output Parameter:
4218 . B - where the copy is put
4219 
4220   Level: intermediate
4221 
4222   Notes:
4223   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4224 
4225   `MatCopy()` copies the matrix entries of a matrix to another existing
4226   matrix (after first zeroing the second matrix).  A related routine is
4227   `MatConvert()`, which first creates a new matrix and then copies the data.
4228 
4229 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4230 @*/
4231 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4232 {
4233   PetscInt i;
4234 
4235   PetscFunctionBegin;
4236   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4237   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4238   PetscValidType(A, 1);
4239   PetscValidType(B, 2);
4240   PetscCheckSameComm(A, 1, B, 2);
4241   MatCheckPreallocated(B, 2);
4242   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4243   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4244   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N,
4245              A->cmap->N, B->cmap->N);
4246   MatCheckPreallocated(A, 1);
4247   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4248 
4249   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4250   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4251   else PetscCall(MatCopy_Basic(A, B, str));
4252 
4253   B->stencil.dim = A->stencil.dim;
4254   B->stencil.noc = A->stencil.noc;
4255   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4256     B->stencil.dims[i]   = A->stencil.dims[i];
4257     B->stencil.starts[i] = A->stencil.starts[i];
4258   }
4259 
4260   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4261   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4262   PetscFunctionReturn(PETSC_SUCCESS);
4263 }
4264 
4265 /*@C
4266   MatConvert - Converts a matrix to another matrix, either of the same
4267   or different type.
4268 
4269   Collective
4270 
4271   Input Parameters:
4272 + mat     - the matrix
4273 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4274    same type as the original matrix.
4275 - reuse   - denotes if the destination matrix is to be created or reused.
4276    Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use
4277    `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused).
4278 
4279   Output Parameter:
4280 . M - pointer to place new matrix
4281 
4282   Level: intermediate
4283 
4284   Notes:
4285   `MatConvert()` first creates a new matrix and then copies the data from
4286   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4287   entries of one matrix to another already existing matrix context.
4288 
4289   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4290   the MPI communicator of the generated matrix is always the same as the communicator
4291   of the input matrix.
4292 
4293 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4294 @*/
4295 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4296 {
4297   PetscBool  sametype, issame, flg;
4298   PetscBool3 issymmetric, ishermitian;
4299   char       convname[256], mtype[256];
4300   Mat        B;
4301 
4302   PetscFunctionBegin;
4303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4304   PetscValidType(mat, 1);
4305   PetscAssertPointer(M, 4);
4306   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4307   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4308   MatCheckPreallocated(mat, 1);
4309 
4310   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4311   if (flg) newtype = mtype;
4312 
4313   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4314   PetscCall(PetscStrcmp(newtype, "same", &issame));
4315   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4316   if (reuse == MAT_REUSE_MATRIX) {
4317     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4318     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4319   }
4320 
4321   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4322     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4323     PetscFunctionReturn(PETSC_SUCCESS);
4324   }
4325 
4326   /* Cache Mat options because some converters use MatHeaderReplace  */
4327   issymmetric = mat->symmetric;
4328   ishermitian = mat->hermitian;
4329 
4330   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4331     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4332     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4333   } else {
4334     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4335     const char *prefix[3]                                 = {"seq", "mpi", ""};
4336     PetscInt    i;
4337     /*
4338        Order of precedence:
4339        0) See if newtype is a superclass of the current matrix.
4340        1) See if a specialized converter is known to the current matrix.
4341        2) See if a specialized converter is known to the desired matrix class.
4342        3) See if a good general converter is registered for the desired class
4343           (as of 6/27/03 only MATMPIADJ falls into this category).
4344        4) See if a good general converter is known for the current matrix.
4345        5) Use a really basic converter.
4346     */
4347 
4348     /* 0) See if newtype is a superclass of the current matrix.
4349           i.e mat is mpiaij and newtype is aij */
4350     for (i = 0; i < 2; i++) {
4351       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4353       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4354       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4355       if (flg) {
4356         if (reuse == MAT_INPLACE_MATRIX) {
4357           PetscCall(PetscInfo(mat, "Early return\n"));
4358           PetscFunctionReturn(PETSC_SUCCESS);
4359         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4360           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4361           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4362           PetscFunctionReturn(PETSC_SUCCESS);
4363         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4364           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4365           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4366           PetscFunctionReturn(PETSC_SUCCESS);
4367         }
4368       }
4369     }
4370     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4371     for (i = 0; i < 3; i++) {
4372       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4373       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4374       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4378       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4379       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4380       if (conv) goto foundconv;
4381     }
4382 
4383     /* 2)  See if a specialized converter is known to the desired matrix class. */
4384     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4385     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4386     PetscCall(MatSetType(B, newtype));
4387     for (i = 0; i < 3; i++) {
4388       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4390       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4394       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4395       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4396       if (conv) {
4397         PetscCall(MatDestroy(&B));
4398         goto foundconv;
4399       }
4400     }
4401 
4402     /* 3) See if a good general converter is registered for the desired class */
4403     conv = B->ops->convertfrom;
4404     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4405     PetscCall(MatDestroy(&B));
4406     if (conv) goto foundconv;
4407 
4408     /* 4) See if a good general converter is known for the current matrix */
4409     if (mat->ops->convert) conv = mat->ops->convert;
4410     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4411     if (conv) goto foundconv;
4412 
4413     /* 5) Use a really basic converter. */
4414     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4415     conv = MatConvert_Basic;
4416 
4417   foundconv:
4418     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4419     PetscCall((*conv)(mat, newtype, reuse, M));
4420     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4421       /* the block sizes must be same if the mappings are copied over */
4422       (*M)->rmap->bs = mat->rmap->bs;
4423       (*M)->cmap->bs = mat->cmap->bs;
4424       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4425       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4426       (*M)->rmap->mapping = mat->rmap->mapping;
4427       (*M)->cmap->mapping = mat->cmap->mapping;
4428     }
4429     (*M)->stencil.dim = mat->stencil.dim;
4430     (*M)->stencil.noc = mat->stencil.noc;
4431     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4432       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4433       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4434     }
4435     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4436   }
4437   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4438 
4439   /* Copy Mat options */
4440   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4441   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4442   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4443   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4444   PetscFunctionReturn(PETSC_SUCCESS);
4445 }
4446 
4447 /*@C
4448   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4449 
4450   Not Collective
4451 
4452   Input Parameter:
4453 . mat - the matrix, must be a factored matrix
4454 
4455   Output Parameter:
4456 . type - the string name of the package (do not free this string)
4457 
4458   Level: intermediate
4459 
4460   Fortran Note:
4461   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4462 
4463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4464 @*/
4465 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4466 {
4467   PetscErrorCode (*conv)(Mat, MatSolverType *);
4468 
4469   PetscFunctionBegin;
4470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4471   PetscValidType(mat, 1);
4472   PetscAssertPointer(type, 2);
4473   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4474   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4475   if (conv) PetscCall((*conv)(mat, type));
4476   else *type = MATSOLVERPETSC;
4477   PetscFunctionReturn(PETSC_SUCCESS);
4478 }
4479 
4480 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4481 struct _MatSolverTypeForSpecifcType {
4482   MatType mtype;
4483   /* no entry for MAT_FACTOR_NONE */
4484   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4485   MatSolverTypeForSpecifcType next;
4486 };
4487 
4488 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4489 struct _MatSolverTypeHolder {
4490   char                       *name;
4491   MatSolverTypeForSpecifcType handlers;
4492   MatSolverTypeHolder         next;
4493 };
4494 
4495 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4496 
4497 /*@C
4498   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4499 
4500   Input Parameters:
4501 + package      - name of the package, for example petsc or superlu
4502 . mtype        - the matrix type that works with this package
4503 . ftype        - the type of factorization supported by the package
4504 - createfactor - routine that will create the factored matrix ready to be used
4505 
4506   Level: developer
4507 
4508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4509   `MatGetFactor()`
4510 @*/
4511 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4512 {
4513   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4514   PetscBool                   flg;
4515   MatSolverTypeForSpecifcType inext, iprev = NULL;
4516 
4517   PetscFunctionBegin;
4518   PetscCall(MatInitializePackage());
4519   if (!next) {
4520     PetscCall(PetscNew(&MatSolverTypeHolders));
4521     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4522     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4523     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4524     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4525     PetscFunctionReturn(PETSC_SUCCESS);
4526   }
4527   while (next) {
4528     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4529     if (flg) {
4530       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4531       inext = next->handlers;
4532       while (inext) {
4533         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4534         if (flg) {
4535           inext->createfactor[(int)ftype - 1] = createfactor;
4536           PetscFunctionReturn(PETSC_SUCCESS);
4537         }
4538         iprev = inext;
4539         inext = inext->next;
4540       }
4541       PetscCall(PetscNew(&iprev->next));
4542       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4543       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4544       PetscFunctionReturn(PETSC_SUCCESS);
4545     }
4546     prev = next;
4547     next = next->next;
4548   }
4549   PetscCall(PetscNew(&prev->next));
4550   PetscCall(PetscStrallocpy(package, &prev->next->name));
4551   PetscCall(PetscNew(&prev->next->handlers));
4552   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4553   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4554   PetscFunctionReturn(PETSC_SUCCESS);
4555 }
4556 
4557 /*@C
4558   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4559 
4560   Input Parameters:
4561 + type  - name of the package, for example petsc or superlu, if this is 'NULL' then the first result that satisfies the other criteria is returned
4562 . ftype - the type of factorization supported by the type
4563 - mtype - the matrix type that works with this type
4564 
4565   Output Parameters:
4566 + foundtype    - `PETSC_TRUE` if the type was registered
4567 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4568 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4569 
4570   Calling sequence of `createfactor`:
4571 + A     - the matrix providing the factor matrix
4572 . mtype - the `MatType` of the factor requested
4573 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4574 
4575   Level: developer
4576 
4577   Note:
4578   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4579   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4580   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4581 
4582 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4583           `MatInitializePackage()`
4584 @*/
4585 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4586 {
4587   MatSolverTypeHolder         next = MatSolverTypeHolders;
4588   PetscBool                   flg;
4589   MatSolverTypeForSpecifcType inext;
4590 
4591   PetscFunctionBegin;
4592   if (foundtype) *foundtype = PETSC_FALSE;
4593   if (foundmtype) *foundmtype = PETSC_FALSE;
4594   if (createfactor) *createfactor = NULL;
4595 
4596   if (type) {
4597     while (next) {
4598       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4599       if (flg) {
4600         if (foundtype) *foundtype = PETSC_TRUE;
4601         inext = next->handlers;
4602         while (inext) {
4603           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4604           if (flg) {
4605             if (foundmtype) *foundmtype = PETSC_TRUE;
4606             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4607             PetscFunctionReturn(PETSC_SUCCESS);
4608           }
4609           inext = inext->next;
4610         }
4611       }
4612       next = next->next;
4613     }
4614   } else {
4615     while (next) {
4616       inext = next->handlers;
4617       while (inext) {
4618         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4619         if (flg && inext->createfactor[(int)ftype - 1]) {
4620           if (foundtype) *foundtype = PETSC_TRUE;
4621           if (foundmtype) *foundmtype = PETSC_TRUE;
4622           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4623           PetscFunctionReturn(PETSC_SUCCESS);
4624         }
4625         inext = inext->next;
4626       }
4627       next = next->next;
4628     }
4629     /* try with base classes inext->mtype */
4630     next = MatSolverTypeHolders;
4631     while (next) {
4632       inext = next->handlers;
4633       while (inext) {
4634         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4635         if (flg && inext->createfactor[(int)ftype - 1]) {
4636           if (foundtype) *foundtype = PETSC_TRUE;
4637           if (foundmtype) *foundmtype = PETSC_TRUE;
4638           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4639           PetscFunctionReturn(PETSC_SUCCESS);
4640         }
4641         inext = inext->next;
4642       }
4643       next = next->next;
4644     }
4645   }
4646   PetscFunctionReturn(PETSC_SUCCESS);
4647 }
4648 
4649 PetscErrorCode MatSolverTypeDestroy(void)
4650 {
4651   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4652   MatSolverTypeForSpecifcType inext, iprev;
4653 
4654   PetscFunctionBegin;
4655   while (next) {
4656     PetscCall(PetscFree(next->name));
4657     inext = next->handlers;
4658     while (inext) {
4659       PetscCall(PetscFree(inext->mtype));
4660       iprev = inext;
4661       inext = inext->next;
4662       PetscCall(PetscFree(iprev));
4663     }
4664     prev = next;
4665     next = next->next;
4666     PetscCall(PetscFree(prev));
4667   }
4668   MatSolverTypeHolders = NULL;
4669   PetscFunctionReturn(PETSC_SUCCESS);
4670 }
4671 
4672 /*@C
4673   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4674 
4675   Logically Collective
4676 
4677   Input Parameter:
4678 . mat - the matrix
4679 
4680   Output Parameter:
4681 . flg - `PETSC_TRUE` if uses the ordering
4682 
4683   Level: developer
4684 
4685   Note:
4686   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4687   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4688 
4689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4690 @*/
4691 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4692 {
4693   PetscFunctionBegin;
4694   *flg = mat->canuseordering;
4695   PetscFunctionReturn(PETSC_SUCCESS);
4696 }
4697 
4698 /*@C
4699   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4700 
4701   Logically Collective
4702 
4703   Input Parameters:
4704 + mat   - the matrix obtained with `MatGetFactor()`
4705 - ftype - the factorization type to be used
4706 
4707   Output Parameter:
4708 . otype - the preferred ordering type
4709 
4710   Level: developer
4711 
4712 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4713 @*/
4714 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4715 {
4716   PetscFunctionBegin;
4717   *otype = mat->preferredordering[ftype];
4718   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4719   PetscFunctionReturn(PETSC_SUCCESS);
4720 }
4721 
4722 /*@C
4723   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4724 
4725   Collective
4726 
4727   Input Parameters:
4728 + mat   - the matrix
4729 . type  - name of solver type, for example, superlu, petsc (to use PETSc's solver if it is available), if this is 'NULL' then the first result that satisfies
4730           the other criteria is returned
4731 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4732 
4733   Output Parameter:
4734 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4735 
4736   Options Database Keys:
4737 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4738 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4739                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4740 
4741   Level: intermediate
4742 
4743   Notes:
4744   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4745   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4746 
4747   Users usually access the factorization solvers via `KSP`
4748 
4749   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4750   such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir
4751 
4752   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4753   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4754   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4755 
4756   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4757   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4758   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4759 
4760   Developer Note:
4761   This should actually be called `MatCreateFactor()` since it creates a new factor object
4762 
4763 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4764           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4765           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4766 @*/
4767 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4768 {
4769   PetscBool foundtype, foundmtype;
4770   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4771 
4772   PetscFunctionBegin;
4773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4774   PetscValidType(mat, 1);
4775 
4776   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4777   MatCheckPreallocated(mat, 1);
4778 
4779   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4780   if (!foundtype) {
4781     if (type) {
4782       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],
4783               ((PetscObject)mat)->type_name, type);
4784     } else {
4785       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);
4786     }
4787   }
4788   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4789   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);
4790 
4791   PetscCall((*conv)(mat, ftype, f));
4792   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4793   PetscFunctionReturn(PETSC_SUCCESS);
4794 }
4795 
4796 /*@C
4797   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4798 
4799   Not Collective
4800 
4801   Input Parameters:
4802 + mat   - the matrix
4803 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4804 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4805 
4806   Output Parameter:
4807 . flg - PETSC_TRUE if the factorization is available
4808 
4809   Level: intermediate
4810 
4811   Notes:
4812   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4813   such as pastix, superlu, mumps etc.
4814 
4815   PETSc must have been ./configure to use the external solver, using the option --download-package
4816 
4817   Developer Note:
4818   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4819 
4820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4821           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4822 @*/
4823 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4824 {
4825   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4826 
4827   PetscFunctionBegin;
4828   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4829   PetscAssertPointer(flg, 4);
4830 
4831   *flg = PETSC_FALSE;
4832   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4833 
4834   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4835   MatCheckPreallocated(mat, 1);
4836 
4837   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4838   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4839   PetscFunctionReturn(PETSC_SUCCESS);
4840 }
4841 
4842 /*@
4843   MatDuplicate - Duplicates a matrix including the non-zero structure.
4844 
4845   Collective
4846 
4847   Input Parameters:
4848 + mat - the matrix
4849 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4850         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4851 
4852   Output Parameter:
4853 . M - pointer to place new matrix
4854 
4855   Level: intermediate
4856 
4857   Notes:
4858   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4859 
4860   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4861 
4862   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.
4863 
4864   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4865   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4866   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4867 
4868 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4869 @*/
4870 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4871 {
4872   Mat         B;
4873   VecType     vtype;
4874   PetscInt    i;
4875   PetscObject dm, container_h, container_d;
4876   void (*viewf)(void);
4877 
4878   PetscFunctionBegin;
4879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4880   PetscValidType(mat, 1);
4881   PetscAssertPointer(M, 3);
4882   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4883   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4884   MatCheckPreallocated(mat, 1);
4885 
4886   *M = NULL;
4887   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4888   PetscUseTypeMethod(mat, duplicate, op, M);
4889   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4890   B = *M;
4891 
4892   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4893   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4894   PetscCall(MatGetVecType(mat, &vtype));
4895   PetscCall(MatSetVecType(B, vtype));
4896 
4897   B->stencil.dim = mat->stencil.dim;
4898   B->stencil.noc = mat->stencil.noc;
4899   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4900     B->stencil.dims[i]   = mat->stencil.dims[i];
4901     B->stencil.starts[i] = mat->stencil.starts[i];
4902   }
4903 
4904   B->nooffproczerorows = mat->nooffproczerorows;
4905   B->nooffprocentries  = mat->nooffprocentries;
4906 
4907   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4908   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4909   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4910   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4911   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4912   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4913   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4914   PetscFunctionReturn(PETSC_SUCCESS);
4915 }
4916 
4917 /*@
4918   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4919 
4920   Logically Collective
4921 
4922   Input Parameter:
4923 . mat - the matrix
4924 
4925   Output Parameter:
4926 . v - the diagonal of the matrix
4927 
4928   Level: intermediate
4929 
4930   Note:
4931   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4932   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4933   is larger than `ndiag`, the values of the remaining entries are unspecified.
4934 
4935   Currently only correct in parallel for square matrices.
4936 
4937 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4938 @*/
4939 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4940 {
4941   PetscFunctionBegin;
4942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4943   PetscValidType(mat, 1);
4944   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4945   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4946   MatCheckPreallocated(mat, 1);
4947   if (PetscDefined(USE_DEBUG)) {
4948     PetscInt nv, row, col, ndiag;
4949 
4950     PetscCall(VecGetLocalSize(v, &nv));
4951     PetscCall(MatGetLocalSize(mat, &row, &col));
4952     ndiag = PetscMin(row, col);
4953     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);
4954   }
4955 
4956   PetscUseTypeMethod(mat, getdiagonal, v);
4957   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4958   PetscFunctionReturn(PETSC_SUCCESS);
4959 }
4960 
4961 /*@C
4962   MatGetRowMin - Gets the minimum value (of the real part) of each
4963   row of the matrix
4964 
4965   Logically Collective
4966 
4967   Input Parameter:
4968 . mat - the matrix
4969 
4970   Output Parameters:
4971 + v   - the vector for storing the maximums
4972 - idx - the indices of the column found for each row (optional)
4973 
4974   Level: intermediate
4975 
4976   Note:
4977   The result of this call are the same as if one converted the matrix to dense format
4978   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4979 
4980   This code is only implemented for a couple of matrix formats.
4981 
4982 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4983           `MatGetRowMax()`
4984 @*/
4985 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4986 {
4987   PetscFunctionBegin;
4988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4989   PetscValidType(mat, 1);
4990   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4991   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4992 
4993   if (!mat->cmap->N) {
4994     PetscCall(VecSet(v, PETSC_MAX_REAL));
4995     if (idx) {
4996       PetscInt i, m = mat->rmap->n;
4997       for (i = 0; i < m; i++) idx[i] = -1;
4998     }
4999   } else {
5000     MatCheckPreallocated(mat, 1);
5001   }
5002   PetscUseTypeMethod(mat, getrowmin, v, idx);
5003   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5004   PetscFunctionReturn(PETSC_SUCCESS);
5005 }
5006 
5007 /*@C
5008   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5009   row of the matrix
5010 
5011   Logically Collective
5012 
5013   Input Parameter:
5014 . mat - the matrix
5015 
5016   Output Parameters:
5017 + v   - the vector for storing the minimums
5018 - idx - the indices of the column found for each row (or `NULL` if not needed)
5019 
5020   Level: intermediate
5021 
5022   Notes:
5023   if a row is completely empty or has only 0.0 values then the `idx` value for that
5024   row is 0 (the first column).
5025 
5026   This code is only implemented for a couple of matrix formats.
5027 
5028 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5029 @*/
5030 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5031 {
5032   PetscFunctionBegin;
5033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5034   PetscValidType(mat, 1);
5035   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5036   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5037   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5038 
5039   if (!mat->cmap->N) {
5040     PetscCall(VecSet(v, 0.0));
5041     if (idx) {
5042       PetscInt i, m = mat->rmap->n;
5043       for (i = 0; i < m; i++) idx[i] = -1;
5044     }
5045   } else {
5046     MatCheckPreallocated(mat, 1);
5047     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5048     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5049   }
5050   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5051   PetscFunctionReturn(PETSC_SUCCESS);
5052 }
5053 
5054 /*@C
5055   MatGetRowMax - Gets the maximum value (of the real part) of each
5056   row of the matrix
5057 
5058   Logically Collective
5059 
5060   Input Parameter:
5061 . mat - the matrix
5062 
5063   Output Parameters:
5064 + v   - the vector for storing the maximums
5065 - idx - the indices of the column found for each row (optional)
5066 
5067   Level: intermediate
5068 
5069   Notes:
5070   The result of this call are the same as if one converted the matrix to dense format
5071   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5072 
5073   This code is only implemented for a couple of matrix formats.
5074 
5075 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5076 @*/
5077 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5078 {
5079   PetscFunctionBegin;
5080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5081   PetscValidType(mat, 1);
5082   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5083   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5084 
5085   if (!mat->cmap->N) {
5086     PetscCall(VecSet(v, PETSC_MIN_REAL));
5087     if (idx) {
5088       PetscInt i, m = mat->rmap->n;
5089       for (i = 0; i < m; i++) idx[i] = -1;
5090     }
5091   } else {
5092     MatCheckPreallocated(mat, 1);
5093     PetscUseTypeMethod(mat, getrowmax, v, idx);
5094   }
5095   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5096   PetscFunctionReturn(PETSC_SUCCESS);
5097 }
5098 
5099 /*@C
5100   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5101   row of the matrix
5102 
5103   Logically Collective
5104 
5105   Input Parameter:
5106 . mat - the matrix
5107 
5108   Output Parameters:
5109 + v   - the vector for storing the maximums
5110 - idx - the indices of the column found for each row (or `NULL` if not needed)
5111 
5112   Level: intermediate
5113 
5114   Notes:
5115   if a row is completely empty or has only 0.0 values then the `idx` value for that
5116   row is 0 (the first column).
5117 
5118   This code is only implemented for a couple of matrix formats.
5119 
5120 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5121 @*/
5122 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5123 {
5124   PetscFunctionBegin;
5125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5126   PetscValidType(mat, 1);
5127   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5128   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5129 
5130   if (!mat->cmap->N) {
5131     PetscCall(VecSet(v, 0.0));
5132     if (idx) {
5133       PetscInt i, m = mat->rmap->n;
5134       for (i = 0; i < m; i++) idx[i] = -1;
5135     }
5136   } else {
5137     MatCheckPreallocated(mat, 1);
5138     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5139     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5140   }
5141   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5142   PetscFunctionReturn(PETSC_SUCCESS);
5143 }
5144 
5145 /*@
5146   MatGetRowSum - Gets the sum of each row of the matrix
5147 
5148   Logically or Neighborhood Collective
5149 
5150   Input Parameter:
5151 . mat - the matrix
5152 
5153   Output Parameter:
5154 . v - the vector for storing the sum of rows
5155 
5156   Level: intermediate
5157 
5158   Note:
5159   This code is slow since it is not currently specialized for different formats
5160 
5161 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5162 @*/
5163 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5164 {
5165   Vec ones;
5166 
5167   PetscFunctionBegin;
5168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5169   PetscValidType(mat, 1);
5170   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5171   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5172   MatCheckPreallocated(mat, 1);
5173   PetscCall(MatCreateVecs(mat, &ones, NULL));
5174   PetscCall(VecSet(ones, 1.));
5175   PetscCall(MatMult(mat, ones, v));
5176   PetscCall(VecDestroy(&ones));
5177   PetscFunctionReturn(PETSC_SUCCESS);
5178 }
5179 
5180 /*@
5181   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5182   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5183 
5184   Collective
5185 
5186   Input Parameter:
5187 . mat - the matrix to provide the transpose
5188 
5189   Output Parameter:
5190 . 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
5191 
5192   Level: advanced
5193 
5194   Note:
5195   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
5196   routine allows bypassing that call.
5197 
5198 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5199 @*/
5200 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5201 {
5202   PetscContainer  rB = NULL;
5203   MatParentState *rb = NULL;
5204 
5205   PetscFunctionBegin;
5206   PetscCall(PetscNew(&rb));
5207   rb->id    = ((PetscObject)mat)->id;
5208   rb->state = 0;
5209   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5210   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5211   PetscCall(PetscContainerSetPointer(rB, rb));
5212   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5213   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5214   PetscCall(PetscObjectDereference((PetscObject)rB));
5215   PetscFunctionReturn(PETSC_SUCCESS);
5216 }
5217 
5218 /*@
5219   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5220 
5221   Collective
5222 
5223   Input Parameters:
5224 + mat   - the matrix to transpose
5225 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5226 
5227   Output Parameter:
5228 . B - the transpose
5229 
5230   Level: intermediate
5231 
5232   Notes:
5233   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5234 
5235   `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
5236   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5237 
5238   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.
5239 
5240   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5241 
5242   If mat is unchanged from the last call this function returns immediately without recomputing the result
5243 
5244   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5245 
5246 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5247           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5248 @*/
5249 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5250 {
5251   PetscContainer  rB = NULL;
5252   MatParentState *rb = NULL;
5253 
5254   PetscFunctionBegin;
5255   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5256   PetscValidType(mat, 1);
5257   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5258   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5259   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5260   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5261   MatCheckPreallocated(mat, 1);
5262   if (reuse == MAT_REUSE_MATRIX) {
5263     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5264     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5265     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5266     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5267     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5268   }
5269 
5270   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5271   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5272     PetscUseTypeMethod(mat, transpose, reuse, B);
5273     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5274   }
5275   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5276 
5277   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5278   if (reuse != MAT_INPLACE_MATRIX) {
5279     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5280     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5281     rb->state        = ((PetscObject)mat)->state;
5282     rb->nonzerostate = mat->nonzerostate;
5283   }
5284   PetscFunctionReturn(PETSC_SUCCESS);
5285 }
5286 
5287 /*@
5288   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5289 
5290   Collective
5291 
5292   Input Parameter:
5293 . A - the matrix to transpose
5294 
5295   Output Parameter:
5296 . 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
5297       numerical portion.
5298 
5299   Level: intermediate
5300 
5301   Note:
5302   This is not supported for many matrix types, use `MatTranspose()` in those cases
5303 
5304 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5305 @*/
5306 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5307 {
5308   PetscFunctionBegin;
5309   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5310   PetscValidType(A, 1);
5311   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5312   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5313   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5314   PetscUseTypeMethod(A, transposesymbolic, B);
5315   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5316 
5317   PetscCall(MatTransposeSetPrecursor(A, *B));
5318   PetscFunctionReturn(PETSC_SUCCESS);
5319 }
5320 
5321 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5322 {
5323   PetscContainer  rB;
5324   MatParentState *rb;
5325 
5326   PetscFunctionBegin;
5327   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5328   PetscValidType(A, 1);
5329   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5330   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5331   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5332   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5333   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5334   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5335   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5336   PetscFunctionReturn(PETSC_SUCCESS);
5337 }
5338 
5339 /*@
5340   MatIsTranspose - Test whether a matrix is another one's transpose,
5341   or its own, in which case it tests symmetry.
5342 
5343   Collective
5344 
5345   Input Parameters:
5346 + A   - the matrix to test
5347 . B   - the matrix to test against, this can equal the first parameter
5348 - tol - tolerance, differences between entries smaller than this are counted as zero
5349 
5350   Output Parameter:
5351 . flg - the result
5352 
5353   Level: intermediate
5354 
5355   Notes:
5356   Only available for `MATAIJ` matrices.
5357 
5358   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5359   test involves parallel copies of the block off-diagonal parts of the matrix.
5360 
5361 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5362 @*/
5363 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5364 {
5365   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5366 
5367   PetscFunctionBegin;
5368   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5369   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5370   PetscAssertPointer(flg, 4);
5371   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5372   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5373   *flg = PETSC_FALSE;
5374   if (f && g) {
5375     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5376     PetscCall((*f)(A, B, tol, flg));
5377   } else {
5378     MatType mattype;
5379 
5380     PetscCall(MatGetType(f ? B : A, &mattype));
5381     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5382   }
5383   PetscFunctionReturn(PETSC_SUCCESS);
5384 }
5385 
5386 /*@
5387   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5388 
5389   Collective
5390 
5391   Input Parameters:
5392 + mat   - the matrix to transpose and complex conjugate
5393 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5394 
5395   Output Parameter:
5396 . B - the Hermitian transpose
5397 
5398   Level: intermediate
5399 
5400 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5401 @*/
5402 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5403 {
5404   PetscFunctionBegin;
5405   PetscCall(MatTranspose(mat, reuse, B));
5406 #if defined(PETSC_USE_COMPLEX)
5407   PetscCall(MatConjugate(*B));
5408 #endif
5409   PetscFunctionReturn(PETSC_SUCCESS);
5410 }
5411 
5412 /*@
5413   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5414 
5415   Collective
5416 
5417   Input Parameters:
5418 + A   - the matrix to test
5419 . B   - the matrix to test against, this can equal the first parameter
5420 - tol - tolerance, differences between entries smaller than this are counted as zero
5421 
5422   Output Parameter:
5423 . flg - the result
5424 
5425   Level: intermediate
5426 
5427   Notes:
5428   Only available for `MATAIJ` matrices.
5429 
5430   The sequential algorithm
5431   has a running time of the order of the number of nonzeros; the parallel
5432   test involves parallel copies of the block off-diagonal parts of the matrix.
5433 
5434 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5435 @*/
5436 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5437 {
5438   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5439 
5440   PetscFunctionBegin;
5441   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5442   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5443   PetscAssertPointer(flg, 4);
5444   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5445   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5446   if (f && g) {
5447     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5448     PetscCall((*f)(A, B, tol, flg));
5449   }
5450   PetscFunctionReturn(PETSC_SUCCESS);
5451 }
5452 
5453 /*@
5454   MatPermute - Creates a new matrix with rows and columns permuted from the
5455   original.
5456 
5457   Collective
5458 
5459   Input Parameters:
5460 + mat - the matrix to permute
5461 . row - row permutation, each processor supplies only the permutation for its rows
5462 - col - column permutation, each processor supplies only the permutation for its columns
5463 
5464   Output Parameter:
5465 . B - the permuted matrix
5466 
5467   Level: advanced
5468 
5469   Note:
5470   The index sets map from row/col of permuted matrix to row/col of original matrix.
5471   The index sets should be on the same communicator as mat and have the same local sizes.
5472 
5473   Developer Note:
5474   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5475   exploit the fact that row and col are permutations, consider implementing the
5476   more general `MatCreateSubMatrix()` instead.
5477 
5478 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5479 @*/
5480 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5481 {
5482   PetscFunctionBegin;
5483   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5484   PetscValidType(mat, 1);
5485   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5486   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5487   PetscAssertPointer(B, 4);
5488   PetscCheckSameComm(mat, 1, row, 2);
5489   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5492   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5493   MatCheckPreallocated(mat, 1);
5494 
5495   if (mat->ops->permute) {
5496     PetscUseTypeMethod(mat, permute, row, col, B);
5497     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5498   } else {
5499     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5500   }
5501   PetscFunctionReturn(PETSC_SUCCESS);
5502 }
5503 
5504 /*@
5505   MatEqual - Compares two matrices.
5506 
5507   Collective
5508 
5509   Input Parameters:
5510 + A - the first matrix
5511 - B - the second matrix
5512 
5513   Output Parameter:
5514 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5515 
5516   Level: intermediate
5517 
5518 .seealso: [](ch_matrices), `Mat`
5519 @*/
5520 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5521 {
5522   PetscFunctionBegin;
5523   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5524   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5525   PetscValidType(A, 1);
5526   PetscValidType(B, 2);
5527   PetscAssertPointer(flg, 3);
5528   PetscCheckSameComm(A, 1, B, 2);
5529   MatCheckPreallocated(A, 1);
5530   MatCheckPreallocated(B, 2);
5531   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5532   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5533   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,
5534              B->cmap->N);
5535   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5536     PetscUseTypeMethod(A, equal, B, flg);
5537   } else {
5538     PetscCall(MatMultEqual(A, B, 10, flg));
5539   }
5540   PetscFunctionReturn(PETSC_SUCCESS);
5541 }
5542 
5543 /*@
5544   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5545   matrices that are stored as vectors.  Either of the two scaling
5546   matrices can be `NULL`.
5547 
5548   Collective
5549 
5550   Input Parameters:
5551 + mat - the matrix to be scaled
5552 . l   - the left scaling vector (or `NULL`)
5553 - r   - the right scaling vector (or `NULL`)
5554 
5555   Level: intermediate
5556 
5557   Note:
5558   `MatDiagonalScale()` computes $A = LAR$, where
5559   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5560   The L scales the rows of the matrix, the R scales the columns of the matrix.
5561 
5562 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5563 @*/
5564 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5565 {
5566   PetscFunctionBegin;
5567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5568   PetscValidType(mat, 1);
5569   if (l) {
5570     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5571     PetscCheckSameComm(mat, 1, l, 2);
5572   }
5573   if (r) {
5574     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5575     PetscCheckSameComm(mat, 1, r, 3);
5576   }
5577   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5578   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5579   MatCheckPreallocated(mat, 1);
5580   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5581 
5582   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5583   PetscUseTypeMethod(mat, diagonalscale, l, r);
5584   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5585   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5586   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5587   PetscFunctionReturn(PETSC_SUCCESS);
5588 }
5589 
5590 /*@
5591   MatScale - Scales all elements of a matrix by a given number.
5592 
5593   Logically Collective
5594 
5595   Input Parameters:
5596 + mat - the matrix to be scaled
5597 - a   - the scaling value
5598 
5599   Level: intermediate
5600 
5601 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5602 @*/
5603 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5604 {
5605   PetscFunctionBegin;
5606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5607   PetscValidType(mat, 1);
5608   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5609   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5610   PetscValidLogicalCollectiveScalar(mat, a, 2);
5611   MatCheckPreallocated(mat, 1);
5612 
5613   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5614   if (a != (PetscScalar)1.0) {
5615     PetscUseTypeMethod(mat, scale, a);
5616     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5617   }
5618   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5619   PetscFunctionReturn(PETSC_SUCCESS);
5620 }
5621 
5622 /*@
5623   MatNorm - Calculates various norms of a matrix.
5624 
5625   Collective
5626 
5627   Input Parameters:
5628 + mat  - the matrix
5629 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5630 
5631   Output Parameter:
5632 . nrm - the resulting norm
5633 
5634   Level: intermediate
5635 
5636 .seealso: [](ch_matrices), `Mat`
5637 @*/
5638 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5639 {
5640   PetscFunctionBegin;
5641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5642   PetscValidType(mat, 1);
5643   PetscAssertPointer(nrm, 3);
5644 
5645   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5646   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5647   MatCheckPreallocated(mat, 1);
5648 
5649   PetscUseTypeMethod(mat, norm, type, nrm);
5650   PetscFunctionReturn(PETSC_SUCCESS);
5651 }
5652 
5653 /*
5654      This variable is used to prevent counting of MatAssemblyBegin() that
5655    are called from within a MatAssemblyEnd().
5656 */
5657 static PetscInt MatAssemblyEnd_InUse = 0;
5658 /*@
5659   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5660   be called after completing all calls to `MatSetValues()`.
5661 
5662   Collective
5663 
5664   Input Parameters:
5665 + mat  - the matrix
5666 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5667 
5668   Level: beginner
5669 
5670   Notes:
5671   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5672   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5673 
5674   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5675   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5676   using the matrix.
5677 
5678   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5679   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
5680   a global collective operation requiring all processes that share the matrix.
5681 
5682   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5683   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5684   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5685 
5686 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5687 @*/
5688 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5689 {
5690   PetscFunctionBegin;
5691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5692   PetscValidType(mat, 1);
5693   MatCheckPreallocated(mat, 1);
5694   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5695   if (mat->assembled) {
5696     mat->was_assembled = PETSC_TRUE;
5697     mat->assembled     = PETSC_FALSE;
5698   }
5699 
5700   if (!MatAssemblyEnd_InUse) {
5701     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5702     PetscTryTypeMethod(mat, assemblybegin, type);
5703     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5704   } else PetscTryTypeMethod(mat, assemblybegin, type);
5705   PetscFunctionReturn(PETSC_SUCCESS);
5706 }
5707 
5708 /*@
5709   MatAssembled - Indicates if a matrix has been assembled and is ready for
5710   use; for example, in matrix-vector product.
5711 
5712   Not Collective
5713 
5714   Input Parameter:
5715 . mat - the matrix
5716 
5717   Output Parameter:
5718 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5719 
5720   Level: advanced
5721 
5722 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5723 @*/
5724 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5725 {
5726   PetscFunctionBegin;
5727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5728   PetscAssertPointer(assembled, 2);
5729   *assembled = mat->assembled;
5730   PetscFunctionReturn(PETSC_SUCCESS);
5731 }
5732 
5733 /*@
5734   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5735   be called after `MatAssemblyBegin()`.
5736 
5737   Collective
5738 
5739   Input Parameters:
5740 + mat  - the matrix
5741 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5742 
5743   Options Database Keys:
5744 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5745 . -mat_view ::ascii_info_detail      - Prints more detailed info
5746 . -mat_view                          - Prints matrix in ASCII format
5747 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5748 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5749 . -display <name>                    - Sets display name (default is host)
5750 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5751 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5752 . -viewer_socket_machine <machine>   - Machine to use for socket
5753 . -viewer_socket_port <port>         - Port number to use for socket
5754 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5755 
5756   Level: beginner
5757 
5758 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5759 @*/
5760 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5761 {
5762   static PetscInt inassm = 0;
5763   PetscBool       flg    = PETSC_FALSE;
5764 
5765   PetscFunctionBegin;
5766   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5767   PetscValidType(mat, 1);
5768 
5769   inassm++;
5770   MatAssemblyEnd_InUse++;
5771   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5772     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5773     PetscTryTypeMethod(mat, assemblyend, type);
5774     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5775   } else PetscTryTypeMethod(mat, assemblyend, type);
5776 
5777   /* Flush assembly is not a true assembly */
5778   if (type != MAT_FLUSH_ASSEMBLY) {
5779     if (mat->num_ass) {
5780       if (!mat->symmetry_eternal) {
5781         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5782         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5783       }
5784       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5785       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5786     }
5787     mat->num_ass++;
5788     mat->assembled        = PETSC_TRUE;
5789     mat->ass_nonzerostate = mat->nonzerostate;
5790   }
5791 
5792   mat->insertmode = NOT_SET_VALUES;
5793   MatAssemblyEnd_InUse--;
5794   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5795   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5796     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5797 
5798     if (mat->checksymmetryonassembly) {
5799       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5800       if (flg) {
5801         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5802       } else {
5803         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5804       }
5805     }
5806     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5807   }
5808   inassm--;
5809   PetscFunctionReturn(PETSC_SUCCESS);
5810 }
5811 
5812 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5813 /*@
5814   MatSetOption - Sets a parameter option for a matrix. Some options
5815   may be specific to certain storage formats.  Some options
5816   determine how values will be inserted (or added). Sorted,
5817   row-oriented input will generally assemble the fastest. The default
5818   is row-oriented.
5819 
5820   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5821 
5822   Input Parameters:
5823 + mat - the matrix
5824 . op  - the option, one of those listed below (and possibly others),
5825 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5826 
5827   Options Describing Matrix Structure:
5828 + `MAT_SPD`                         - symmetric positive definite
5829 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5830 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5831 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5832 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5833 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5834 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5835 
5836    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5837    do not need to be computed (usually at a high cost)
5838 
5839    Options For Use with `MatSetValues()`:
5840    Insert a logically dense subblock, which can be
5841 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5842 
5843    These options reflect the data you pass in with `MatSetValues()`; it has
5844    nothing to do with how the data is stored internally in the matrix
5845    data structure.
5846 
5847    When (re)assembling a matrix, we can restrict the input for
5848    efficiency/debugging purposes.  These options include
5849 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5850 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5851 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5852 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5853 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5854 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5855         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5856         performance for very large process counts.
5857 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5858         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5859         functions, instead sending only neighbor messages.
5860 
5861   Level: intermediate
5862 
5863   Notes:
5864   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5865 
5866   Some options are relevant only for particular matrix types and
5867   are thus ignored by others.  Other options are not supported by
5868   certain matrix types and will generate an error message if set.
5869 
5870   If using Fortran to compute a matrix, one may need to
5871   use the column-oriented option (or convert to the row-oriented
5872   format).
5873 
5874   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5875   that would generate a new entry in the nonzero structure is instead
5876   ignored.  Thus, if memory has not already been allocated for this particular
5877   data, then the insertion is ignored. For dense matrices, in which
5878   the entire array is allocated, no entries are ever ignored.
5879   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5880 
5881   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5882   that would generate a new entry in the nonzero structure instead produces
5883   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
5884 
5885   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5886   that would generate a new entry that has not been preallocated will
5887   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5888   only.) This is a useful flag when debugging matrix memory preallocation.
5889   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5890 
5891   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5892   other processors should be dropped, rather than stashed.
5893   This is useful if you know that the "owning" processor is also
5894   always generating the correct matrix entries, so that PETSc need
5895   not transfer duplicate entries generated on another processor.
5896 
5897   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5898   searches during matrix assembly. When this flag is set, the hash table
5899   is created during the first matrix assembly. This hash table is
5900   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5901   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5902   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5903   supported by `MATMPIBAIJ` format only.
5904 
5905   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5906   are kept in the nonzero structure
5907 
5908   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5909   a zero location in the matrix
5910 
5911   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5912 
5913   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5914   zero row routines and thus improves performance for very large process counts.
5915 
5916   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5917   part of the matrix (since they should match the upper triangular part).
5918 
5919   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5920   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5921   with finite difference schemes with non-periodic boundary conditions.
5922 
5923   Developer Note:
5924   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5925   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5926   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5927   not changed.
5928 
5929 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5930 @*/
5931 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5932 {
5933   PetscFunctionBegin;
5934   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5935   if (op > 0) {
5936     PetscValidLogicalCollectiveEnum(mat, op, 2);
5937     PetscValidLogicalCollectiveBool(mat, flg, 3);
5938   }
5939 
5940   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);
5941 
5942   switch (op) {
5943   case MAT_FORCE_DIAGONAL_ENTRIES:
5944     mat->force_diagonals = flg;
5945     PetscFunctionReturn(PETSC_SUCCESS);
5946   case MAT_NO_OFF_PROC_ENTRIES:
5947     mat->nooffprocentries = flg;
5948     PetscFunctionReturn(PETSC_SUCCESS);
5949   case MAT_SUBSET_OFF_PROC_ENTRIES:
5950     mat->assembly_subset = flg;
5951     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5952 #if !defined(PETSC_HAVE_MPIUNI)
5953       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5954 #endif
5955       mat->stash.first_assembly_done = PETSC_FALSE;
5956     }
5957     PetscFunctionReturn(PETSC_SUCCESS);
5958   case MAT_NO_OFF_PROC_ZERO_ROWS:
5959     mat->nooffproczerorows = flg;
5960     PetscFunctionReturn(PETSC_SUCCESS);
5961   case MAT_SPD:
5962     if (flg) {
5963       mat->spd                    = PETSC_BOOL3_TRUE;
5964       mat->symmetric              = PETSC_BOOL3_TRUE;
5965       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5966     } else {
5967       mat->spd = PETSC_BOOL3_FALSE;
5968     }
5969     break;
5970   case MAT_SYMMETRIC:
5971     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5972     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5973 #if !defined(PETSC_USE_COMPLEX)
5974     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5975 #endif
5976     break;
5977   case MAT_HERMITIAN:
5978     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5979     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5980 #if !defined(PETSC_USE_COMPLEX)
5981     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5982 #endif
5983     break;
5984   case MAT_STRUCTURALLY_SYMMETRIC:
5985     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5986     break;
5987   case MAT_SYMMETRY_ETERNAL:
5988     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");
5989     mat->symmetry_eternal = flg;
5990     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5991     break;
5992   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5993     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");
5994     mat->structural_symmetry_eternal = flg;
5995     break;
5996   case MAT_SPD_ETERNAL:
5997     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");
5998     mat->spd_eternal = flg;
5999     if (flg) {
6000       mat->structural_symmetry_eternal = PETSC_TRUE;
6001       mat->symmetry_eternal            = PETSC_TRUE;
6002     }
6003     break;
6004   case MAT_STRUCTURE_ONLY:
6005     mat->structure_only = flg;
6006     break;
6007   case MAT_SORTED_FULL:
6008     mat->sortedfull = flg;
6009     break;
6010   default:
6011     break;
6012   }
6013   PetscTryTypeMethod(mat, setoption, op, flg);
6014   PetscFunctionReturn(PETSC_SUCCESS);
6015 }
6016 
6017 /*@
6018   MatGetOption - Gets a parameter option that has been set for a matrix.
6019 
6020   Logically Collective
6021 
6022   Input Parameters:
6023 + mat - the matrix
6024 - op  - the option, this only responds to certain options, check the code for which ones
6025 
6026   Output Parameter:
6027 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6028 
6029   Level: intermediate
6030 
6031   Notes:
6032   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6033 
6034   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6035   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6036 
6037 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6038     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6039 @*/
6040 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6041 {
6042   PetscFunctionBegin;
6043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6044   PetscValidType(mat, 1);
6045 
6046   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);
6047   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()");
6048 
6049   switch (op) {
6050   case MAT_NO_OFF_PROC_ENTRIES:
6051     *flg = mat->nooffprocentries;
6052     break;
6053   case MAT_NO_OFF_PROC_ZERO_ROWS:
6054     *flg = mat->nooffproczerorows;
6055     break;
6056   case MAT_SYMMETRIC:
6057     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6058     break;
6059   case MAT_HERMITIAN:
6060     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6061     break;
6062   case MAT_STRUCTURALLY_SYMMETRIC:
6063     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6064     break;
6065   case MAT_SPD:
6066     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6067     break;
6068   case MAT_SYMMETRY_ETERNAL:
6069     *flg = mat->symmetry_eternal;
6070     break;
6071   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6072     *flg = mat->symmetry_eternal;
6073     break;
6074   default:
6075     break;
6076   }
6077   PetscFunctionReturn(PETSC_SUCCESS);
6078 }
6079 
6080 /*@
6081   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6082   this routine retains the old nonzero structure.
6083 
6084   Logically Collective
6085 
6086   Input Parameter:
6087 . mat - the matrix
6088 
6089   Level: intermediate
6090 
6091   Note:
6092   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.
6093   See the Performance chapter of the users manual for information on preallocating matrices.
6094 
6095 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6096 @*/
6097 PetscErrorCode MatZeroEntries(Mat mat)
6098 {
6099   PetscFunctionBegin;
6100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6101   PetscValidType(mat, 1);
6102   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6103   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");
6104   MatCheckPreallocated(mat, 1);
6105 
6106   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6107   PetscUseTypeMethod(mat, zeroentries);
6108   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6109   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6110   PetscFunctionReturn(PETSC_SUCCESS);
6111 }
6112 
6113 /*@
6114   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6115   of a set of rows and columns of a matrix.
6116 
6117   Collective
6118 
6119   Input Parameters:
6120 + mat     - the matrix
6121 . numRows - the number of rows/columns to zero
6122 . rows    - the global row indices
6123 . diag    - value put in the diagonal of the eliminated rows
6124 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6125 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6126 
6127   Level: intermediate
6128 
6129   Notes:
6130   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6131 
6132   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6133   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
6134 
6135   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6136   Krylov method to take advantage of the known solution on the zeroed rows.
6137 
6138   For the parallel case, all processes that share the matrix (i.e.,
6139   those in the communicator used for matrix creation) MUST call this
6140   routine, regardless of whether any rows being zeroed are owned by
6141   them.
6142 
6143   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6144 
6145   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6146   list only rows local to itself).
6147 
6148   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6149 
6150 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6151           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6152 @*/
6153 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6154 {
6155   PetscFunctionBegin;
6156   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6157   PetscValidType(mat, 1);
6158   if (numRows) PetscAssertPointer(rows, 3);
6159   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6160   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6161   MatCheckPreallocated(mat, 1);
6162 
6163   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6164   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6165   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6166   PetscFunctionReturn(PETSC_SUCCESS);
6167 }
6168 
6169 /*@
6170   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6171   of a set of rows and columns of a matrix.
6172 
6173   Collective
6174 
6175   Input Parameters:
6176 + mat  - the matrix
6177 . is   - the rows to zero
6178 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6179 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6180 - b    - optional vector of right hand side, that will be adjusted by provided solution
6181 
6182   Level: intermediate
6183 
6184   Note:
6185   See `MatZeroRowsColumns()` for details on how this routine operates.
6186 
6187 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6188           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6189 @*/
6190 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6191 {
6192   PetscInt        numRows;
6193   const PetscInt *rows;
6194 
6195   PetscFunctionBegin;
6196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6197   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6198   PetscValidType(mat, 1);
6199   PetscValidType(is, 2);
6200   PetscCall(ISGetLocalSize(is, &numRows));
6201   PetscCall(ISGetIndices(is, &rows));
6202   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6203   PetscCall(ISRestoreIndices(is, &rows));
6204   PetscFunctionReturn(PETSC_SUCCESS);
6205 }
6206 
6207 /*@
6208   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6209   of a set of rows of a matrix.
6210 
6211   Collective
6212 
6213   Input Parameters:
6214 + mat     - the matrix
6215 . numRows - the number of rows to zero
6216 . rows    - the global row indices
6217 . diag    - value put in the diagonal of the zeroed rows
6218 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6219 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6220 
6221   Level: intermediate
6222 
6223   Notes:
6224   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6225 
6226   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6227 
6228   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6229   Krylov method to take advantage of the known solution on the zeroed rows.
6230 
6231   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)
6232   from the matrix.
6233 
6234   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6235   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
6236   formats this does not alter the nonzero structure.
6237 
6238   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6239   of the matrix is not changed the values are
6240   merely zeroed.
6241 
6242   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6243   formats can optionally remove the main diagonal entry from the
6244   nonzero structure as well, by passing 0.0 as the final argument).
6245 
6246   For the parallel case, all processes that share the matrix (i.e.,
6247   those in the communicator used for matrix creation) MUST call this
6248   routine, regardless of whether any rows being zeroed are owned by
6249   them.
6250 
6251   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6252   list only rows local to itself).
6253 
6254   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6255   owns that are to be zeroed. This saves a global synchronization in the implementation.
6256 
6257 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6258           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6259 @*/
6260 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6261 {
6262   PetscFunctionBegin;
6263   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6264   PetscValidType(mat, 1);
6265   if (numRows) PetscAssertPointer(rows, 3);
6266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6268   MatCheckPreallocated(mat, 1);
6269 
6270   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6271   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6272   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6273   PetscFunctionReturn(PETSC_SUCCESS);
6274 }
6275 
6276 /*@
6277   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6278   of a set of rows of a matrix.
6279 
6280   Collective
6281 
6282   Input Parameters:
6283 + mat  - the matrix
6284 . is   - index set of rows to remove (if `NULL` then no row is removed)
6285 . diag - value put in all diagonals of eliminated rows
6286 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6287 - b    - optional vector of right hand side, that will be adjusted by provided solution
6288 
6289   Level: intermediate
6290 
6291   Note:
6292   See `MatZeroRows()` for details on how this routine operates.
6293 
6294 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6295           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6296 @*/
6297 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6298 {
6299   PetscInt        numRows = 0;
6300   const PetscInt *rows    = NULL;
6301 
6302   PetscFunctionBegin;
6303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6304   PetscValidType(mat, 1);
6305   if (is) {
6306     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6307     PetscCall(ISGetLocalSize(is, &numRows));
6308     PetscCall(ISGetIndices(is, &rows));
6309   }
6310   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6311   if (is) PetscCall(ISRestoreIndices(is, &rows));
6312   PetscFunctionReturn(PETSC_SUCCESS);
6313 }
6314 
6315 /*@
6316   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6317   of a set of rows of a matrix. These rows must be local to the process.
6318 
6319   Collective
6320 
6321   Input Parameters:
6322 + mat     - the matrix
6323 . numRows - the number of rows to remove
6324 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6325 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6326 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6327 - b       - optional vector of right hand side, that will be adjusted by provided solution
6328 
6329   Level: intermediate
6330 
6331   Notes:
6332   See `MatZeroRows()` for details on how this routine operates.
6333 
6334   The grid coordinates are across the entire grid, not just the local portion
6335 
6336   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6337   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6338   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6339   `DM_BOUNDARY_PERIODIC` boundary type.
6340 
6341   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
6342   a single value per point) you can skip filling those indices.
6343 
6344   Fortran Note:
6345   `idxm` and `idxn` should be declared as
6346 $     MatStencil idxm(4, m)
6347   and the values inserted using
6348 .vb
6349     idxm(MatStencil_i, 1) = i
6350     idxm(MatStencil_j, 1) = j
6351     idxm(MatStencil_k, 1) = k
6352     idxm(MatStencil_c, 1) = c
6353    etc
6354 .ve
6355 
6356 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6357           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6358 @*/
6359 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6360 {
6361   PetscInt  dim    = mat->stencil.dim;
6362   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6363   PetscInt *dims   = mat->stencil.dims + 1;
6364   PetscInt *starts = mat->stencil.starts;
6365   PetscInt *dxm    = (PetscInt *)rows;
6366   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6367 
6368   PetscFunctionBegin;
6369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6370   PetscValidType(mat, 1);
6371   if (numRows) PetscAssertPointer(rows, 3);
6372 
6373   PetscCall(PetscMalloc1(numRows, &jdxm));
6374   for (i = 0; i < numRows; ++i) {
6375     /* Skip unused dimensions (they are ordered k, j, i, c) */
6376     for (j = 0; j < 3 - sdim; ++j) dxm++;
6377     /* Local index in X dir */
6378     tmp = *dxm++ - starts[0];
6379     /* Loop over remaining dimensions */
6380     for (j = 0; j < dim - 1; ++j) {
6381       /* If nonlocal, set index to be negative */
6382       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6383       /* Update local index */
6384       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6385     }
6386     /* Skip component slot if necessary */
6387     if (mat->stencil.noc) dxm++;
6388     /* Local row number */
6389     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6390   }
6391   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6392   PetscCall(PetscFree(jdxm));
6393   PetscFunctionReturn(PETSC_SUCCESS);
6394 }
6395 
6396 /*@
6397   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6398   of a set of rows and columns of a matrix.
6399 
6400   Collective
6401 
6402   Input Parameters:
6403 + mat     - the matrix
6404 . numRows - the number of rows/columns to remove
6405 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6406 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6407 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6408 - b       - optional vector of right hand side, that will be adjusted by provided solution
6409 
6410   Level: intermediate
6411 
6412   Notes:
6413   See `MatZeroRowsColumns()` for details on how this routine operates.
6414 
6415   The grid coordinates are across the entire grid, not just the local portion
6416 
6417   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6418   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6419   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6420   `DM_BOUNDARY_PERIODIC` boundary type.
6421 
6422   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
6423   a single value per point) you can skip filling those indices.
6424 
6425   Fortran Note:
6426   `idxm` and `idxn` should be declared as
6427 $     MatStencil idxm(4, m)
6428   and the values inserted using
6429 .vb
6430     idxm(MatStencil_i, 1) = i
6431     idxm(MatStencil_j, 1) = j
6432     idxm(MatStencil_k, 1) = k
6433     idxm(MatStencil_c, 1) = c
6434     etc
6435 .ve
6436 
6437 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6438           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6439 @*/
6440 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6441 {
6442   PetscInt  dim    = mat->stencil.dim;
6443   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6444   PetscInt *dims   = mat->stencil.dims + 1;
6445   PetscInt *starts = mat->stencil.starts;
6446   PetscInt *dxm    = (PetscInt *)rows;
6447   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6448 
6449   PetscFunctionBegin;
6450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6451   PetscValidType(mat, 1);
6452   if (numRows) PetscAssertPointer(rows, 3);
6453 
6454   PetscCall(PetscMalloc1(numRows, &jdxm));
6455   for (i = 0; i < numRows; ++i) {
6456     /* Skip unused dimensions (they are ordered k, j, i, c) */
6457     for (j = 0; j < 3 - sdim; ++j) dxm++;
6458     /* Local index in X dir */
6459     tmp = *dxm++ - starts[0];
6460     /* Loop over remaining dimensions */
6461     for (j = 0; j < dim - 1; ++j) {
6462       /* If nonlocal, set index to be negative */
6463       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6464       /* Update local index */
6465       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6466     }
6467     /* Skip component slot if necessary */
6468     if (mat->stencil.noc) dxm++;
6469     /* Local row number */
6470     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6471   }
6472   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6473   PetscCall(PetscFree(jdxm));
6474   PetscFunctionReturn(PETSC_SUCCESS);
6475 }
6476 
6477 /*@C
6478   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6479   of a set of rows of a matrix; using local numbering of rows.
6480 
6481   Collective
6482 
6483   Input Parameters:
6484 + mat     - the matrix
6485 . numRows - the number of rows to remove
6486 . rows    - the local row indices
6487 . diag    - value put in all diagonals of eliminated rows
6488 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6489 - b       - optional vector of right hand side, that will be adjusted by provided solution
6490 
6491   Level: intermediate
6492 
6493   Notes:
6494   Before calling `MatZeroRowsLocal()`, the user must first set the
6495   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6496 
6497   See `MatZeroRows()` for details on how this routine operates.
6498 
6499 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6500           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6501 @*/
6502 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6503 {
6504   PetscFunctionBegin;
6505   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6506   PetscValidType(mat, 1);
6507   if (numRows) PetscAssertPointer(rows, 3);
6508   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6509   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6510   MatCheckPreallocated(mat, 1);
6511 
6512   if (mat->ops->zerorowslocal) {
6513     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6514   } else {
6515     IS              is, newis;
6516     const PetscInt *newRows;
6517 
6518     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6519     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6520     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6521     PetscCall(ISGetIndices(newis, &newRows));
6522     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6523     PetscCall(ISRestoreIndices(newis, &newRows));
6524     PetscCall(ISDestroy(&newis));
6525     PetscCall(ISDestroy(&is));
6526   }
6527   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6528   PetscFunctionReturn(PETSC_SUCCESS);
6529 }
6530 
6531 /*@
6532   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6533   of a set of rows of a matrix; using local numbering of rows.
6534 
6535   Collective
6536 
6537   Input Parameters:
6538 + mat  - the matrix
6539 . is   - index set of rows to remove
6540 . diag - value put in all diagonals of eliminated rows
6541 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6542 - b    - optional vector of right hand side, that will be adjusted by provided solution
6543 
6544   Level: intermediate
6545 
6546   Notes:
6547   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6548   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6549 
6550   See `MatZeroRows()` for details on how this routine operates.
6551 
6552 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6553           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6554 @*/
6555 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6556 {
6557   PetscInt        numRows;
6558   const PetscInt *rows;
6559 
6560   PetscFunctionBegin;
6561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6562   PetscValidType(mat, 1);
6563   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6564   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6565   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6566   MatCheckPreallocated(mat, 1);
6567 
6568   PetscCall(ISGetLocalSize(is, &numRows));
6569   PetscCall(ISGetIndices(is, &rows));
6570   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6571   PetscCall(ISRestoreIndices(is, &rows));
6572   PetscFunctionReturn(PETSC_SUCCESS);
6573 }
6574 
6575 /*@
6576   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6577   of a set of rows and columns of a matrix; using local numbering of rows.
6578 
6579   Collective
6580 
6581   Input Parameters:
6582 + mat     - the matrix
6583 . numRows - the number of rows to remove
6584 . rows    - the global row indices
6585 . diag    - value put in all diagonals of eliminated rows
6586 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6587 - b       - optional vector of right hand side, that will be adjusted by provided solution
6588 
6589   Level: intermediate
6590 
6591   Notes:
6592   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6593   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6594 
6595   See `MatZeroRowsColumns()` for details on how this routine operates.
6596 
6597 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6598           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6599 @*/
6600 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6601 {
6602   IS              is, newis;
6603   const PetscInt *newRows;
6604 
6605   PetscFunctionBegin;
6606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6607   PetscValidType(mat, 1);
6608   if (numRows) PetscAssertPointer(rows, 3);
6609   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6610   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6611   MatCheckPreallocated(mat, 1);
6612 
6613   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6614   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6615   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6616   PetscCall(ISGetIndices(newis, &newRows));
6617   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6618   PetscCall(ISRestoreIndices(newis, &newRows));
6619   PetscCall(ISDestroy(&newis));
6620   PetscCall(ISDestroy(&is));
6621   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6622   PetscFunctionReturn(PETSC_SUCCESS);
6623 }
6624 
6625 /*@
6626   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6627   of a set of rows and columns of a matrix; using local numbering of rows.
6628 
6629   Collective
6630 
6631   Input Parameters:
6632 + mat  - the matrix
6633 . is   - index set of rows to remove
6634 . diag - value put in all diagonals of eliminated rows
6635 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6636 - b    - optional vector of right hand side, that will be adjusted by provided solution
6637 
6638   Level: intermediate
6639 
6640   Notes:
6641   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6642   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6643 
6644   See `MatZeroRowsColumns()` for details on how this routine operates.
6645 
6646 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6647           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6648 @*/
6649 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6650 {
6651   PetscInt        numRows;
6652   const PetscInt *rows;
6653 
6654   PetscFunctionBegin;
6655   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6656   PetscValidType(mat, 1);
6657   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6658   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6659   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6660   MatCheckPreallocated(mat, 1);
6661 
6662   PetscCall(ISGetLocalSize(is, &numRows));
6663   PetscCall(ISGetIndices(is, &rows));
6664   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6665   PetscCall(ISRestoreIndices(is, &rows));
6666   PetscFunctionReturn(PETSC_SUCCESS);
6667 }
6668 
6669 /*@C
6670   MatGetSize - Returns the numbers of rows and columns in a matrix.
6671 
6672   Not Collective
6673 
6674   Input Parameter:
6675 . mat - the matrix
6676 
6677   Output Parameters:
6678 + m - the number of global rows
6679 - n - the number of global columns
6680 
6681   Level: beginner
6682 
6683   Note:
6684   Both output parameters can be `NULL` on input.
6685 
6686 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6687 @*/
6688 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6689 {
6690   PetscFunctionBegin;
6691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6692   if (m) *m = mat->rmap->N;
6693   if (n) *n = mat->cmap->N;
6694   PetscFunctionReturn(PETSC_SUCCESS);
6695 }
6696 
6697 /*@C
6698   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6699   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6700 
6701   Not Collective
6702 
6703   Input Parameter:
6704 . mat - the matrix
6705 
6706   Output Parameters:
6707 + m - the number of local rows, use `NULL` to not obtain this value
6708 - n - the number of local columns, use `NULL` to not obtain this value
6709 
6710   Level: beginner
6711 
6712 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6713 @*/
6714 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6715 {
6716   PetscFunctionBegin;
6717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6718   if (m) PetscAssertPointer(m, 2);
6719   if (n) PetscAssertPointer(n, 3);
6720   if (m) *m = mat->rmap->n;
6721   if (n) *n = mat->cmap->n;
6722   PetscFunctionReturn(PETSC_SUCCESS);
6723 }
6724 
6725 /*@C
6726   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6727   vector one multiplies this matrix by that are owned by this processor.
6728 
6729   Not Collective, unless matrix has not been allocated, then collective
6730 
6731   Input Parameter:
6732 . mat - the matrix
6733 
6734   Output Parameters:
6735 + m - the global index of the first local column, use `NULL` to not obtain this value
6736 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6737 
6738   Level: developer
6739 
6740   Note:
6741   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6742   Layouts](sec_matlayout) for details on matrix layouts.
6743 
6744 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6745 @*/
6746 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6747 {
6748   PetscFunctionBegin;
6749   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6750   PetscValidType(mat, 1);
6751   if (m) PetscAssertPointer(m, 2);
6752   if (n) PetscAssertPointer(n, 3);
6753   MatCheckPreallocated(mat, 1);
6754   if (m) *m = mat->cmap->rstart;
6755   if (n) *n = mat->cmap->rend;
6756   PetscFunctionReturn(PETSC_SUCCESS);
6757 }
6758 
6759 /*@C
6760   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6761   this MPI process.
6762 
6763   Not Collective
6764 
6765   Input Parameter:
6766 . mat - the matrix
6767 
6768   Output Parameters:
6769 + m - the global index of the first local row, use `NULL` to not obtain this value
6770 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6771 
6772   Level: beginner
6773 
6774   Note:
6775   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6776   would contain the result of a matrix vector product with this matrix. See [Matrix
6777   Layouts](sec_matlayout) for details on matrix layouts.
6778 
6779 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6780           `PetscLayout`
6781 @*/
6782 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6783 {
6784   PetscFunctionBegin;
6785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6786   PetscValidType(mat, 1);
6787   if (m) PetscAssertPointer(m, 2);
6788   if (n) PetscAssertPointer(n, 3);
6789   MatCheckPreallocated(mat, 1);
6790   if (m) *m = mat->rmap->rstart;
6791   if (n) *n = mat->rmap->rend;
6792   PetscFunctionReturn(PETSC_SUCCESS);
6793 }
6794 
6795 /*@C
6796   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6797   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6798 
6799   Not Collective, unless matrix has not been allocated
6800 
6801   Input Parameter:
6802 . mat - the matrix
6803 
6804   Output Parameter:
6805 . ranges - start of each processors portion plus one more than the total length at the end
6806 
6807   Level: beginner
6808 
6809   Note:
6810   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6811   would contain the result of a matrix vector product with this matrix. See [Matrix
6812   Layouts](sec_matlayout) for details on matrix layouts.
6813 
6814 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6815 @*/
6816 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6817 {
6818   PetscFunctionBegin;
6819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6820   PetscValidType(mat, 1);
6821   MatCheckPreallocated(mat, 1);
6822   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6823   PetscFunctionReturn(PETSC_SUCCESS);
6824 }
6825 
6826 /*@C
6827   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6828   vector one multiplies this vector by that are owned by each processor.
6829 
6830   Not Collective, unless matrix has not been allocated
6831 
6832   Input Parameter:
6833 . mat - the matrix
6834 
6835   Output Parameter:
6836 . ranges - start of each processors portion plus one more than the total length at the end
6837 
6838   Level: beginner
6839 
6840   Note:
6841   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6842   Layouts](sec_matlayout) for details on matrix layouts.
6843 
6844 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6845 @*/
6846 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6847 {
6848   PetscFunctionBegin;
6849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6850   PetscValidType(mat, 1);
6851   MatCheckPreallocated(mat, 1);
6852   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6853   PetscFunctionReturn(PETSC_SUCCESS);
6854 }
6855 
6856 /*@C
6857   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6858 
6859   Not Collective
6860 
6861   Input Parameter:
6862 . A - matrix
6863 
6864   Output Parameters:
6865 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6866 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6867 
6868   Level: intermediate
6869 
6870   Note:
6871   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6872   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6873   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6874   details on matrix layouts.
6875 
6876 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6877 @*/
6878 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6879 {
6880   PetscErrorCode (*f)(Mat, IS *, IS *);
6881 
6882   PetscFunctionBegin;
6883   MatCheckPreallocated(A, 1);
6884   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6885   if (f) {
6886     PetscCall((*f)(A, rows, cols));
6887   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6888     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6889     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6890   }
6891   PetscFunctionReturn(PETSC_SUCCESS);
6892 }
6893 
6894 /*@C
6895   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6896   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6897   to complete the factorization.
6898 
6899   Collective
6900 
6901   Input Parameters:
6902 + fact - the factorized matrix obtained with `MatGetFactor()`
6903 . mat  - the matrix
6904 . row  - row permutation
6905 . col  - column permutation
6906 - info - structure containing
6907 .vb
6908       levels - number of levels of fill.
6909       expected fill - as ratio of original fill.
6910       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6911                 missing diagonal entries)
6912 .ve
6913 
6914   Level: developer
6915 
6916   Notes:
6917   See [Matrix Factorization](sec_matfactor) for additional information.
6918 
6919   Most users should employ the `KSP` interface for linear solvers
6920   instead of working directly with matrix algebra routines such as this.
6921   See, e.g., `KSPCreate()`.
6922 
6923   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
6924 
6925   Developer Note:
6926   The Fortran interface is not autogenerated as the
6927   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6928 
6929 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6930           `MatGetOrdering()`, `MatFactorInfo`
6931 @*/
6932 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6933 {
6934   PetscFunctionBegin;
6935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6936   PetscValidType(mat, 2);
6937   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6938   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6939   PetscAssertPointer(info, 5);
6940   PetscAssertPointer(fact, 1);
6941   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6942   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6943   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6944   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6945   MatCheckPreallocated(mat, 2);
6946 
6947   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6948   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6949   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6950   PetscFunctionReturn(PETSC_SUCCESS);
6951 }
6952 
6953 /*@C
6954   MatICCFactorSymbolic - Performs symbolic incomplete
6955   Cholesky factorization for a symmetric matrix.  Use
6956   `MatCholeskyFactorNumeric()` to complete the factorization.
6957 
6958   Collective
6959 
6960   Input Parameters:
6961 + fact - the factorized matrix obtained with `MatGetFactor()`
6962 . mat  - the matrix to be factored
6963 . perm - row and column permutation
6964 - info - structure containing
6965 .vb
6966       levels - number of levels of fill.
6967       expected fill - as ratio of original fill.
6968 .ve
6969 
6970   Level: developer
6971 
6972   Notes:
6973   Most users should employ the `KSP` interface for linear solvers
6974   instead of working directly with matrix algebra routines such as this.
6975   See, e.g., `KSPCreate()`.
6976 
6977   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
6978 
6979   Developer Note:
6980   The Fortran interface is not autogenerated as the
6981   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6982 
6983 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6984 @*/
6985 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6986 {
6987   PetscFunctionBegin;
6988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6989   PetscValidType(mat, 2);
6990   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6991   PetscAssertPointer(info, 4);
6992   PetscAssertPointer(fact, 1);
6993   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6994   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6995   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6996   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6997   MatCheckPreallocated(mat, 2);
6998 
6999   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7000   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7001   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7002   PetscFunctionReturn(PETSC_SUCCESS);
7003 }
7004 
7005 /*@C
7006   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7007   points to an array of valid matrices, they may be reused to store the new
7008   submatrices.
7009 
7010   Collective
7011 
7012   Input Parameters:
7013 + mat   - the matrix
7014 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7015 . irow  - index set of rows to extract
7016 . icol  - index set of columns to extract
7017 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7018 
7019   Output Parameter:
7020 . submat - the array of submatrices
7021 
7022   Level: advanced
7023 
7024   Notes:
7025   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7026   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7027   to extract a parallel submatrix.
7028 
7029   Some matrix types place restrictions on the row and column
7030   indices, such as that they be sorted or that they be equal to each other.
7031 
7032   The index sets may not have duplicate entries.
7033 
7034   When extracting submatrices from a parallel matrix, each processor can
7035   form a different submatrix by setting the rows and columns of its
7036   individual index sets according to the local submatrix desired.
7037 
7038   When finished using the submatrices, the user should destroy
7039   them with `MatDestroySubMatrices()`.
7040 
7041   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7042   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7043 
7044   This routine creates the matrices in submat; you should NOT create them before
7045   calling it. It also allocates the array of matrix pointers submat.
7046 
7047   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7048   request one row/column in a block, they must request all rows/columns that are in
7049   that block. For example, if the block size is 2 you cannot request just row 0 and
7050   column 0.
7051 
7052   Fortran Note:
7053   The Fortran interface is slightly different from that given below; it
7054   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7055 
7056 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7057 @*/
7058 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7059 {
7060   PetscInt  i;
7061   PetscBool eq;
7062 
7063   PetscFunctionBegin;
7064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7065   PetscValidType(mat, 1);
7066   if (n) {
7067     PetscAssertPointer(irow, 3);
7068     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7069     PetscAssertPointer(icol, 4);
7070     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7071   }
7072   PetscAssertPointer(submat, 6);
7073   if (n && scall == MAT_REUSE_MATRIX) {
7074     PetscAssertPointer(*submat, 6);
7075     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7076   }
7077   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7078   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7079   MatCheckPreallocated(mat, 1);
7080   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7081   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7082   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7083   for (i = 0; i < n; i++) {
7084     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7085     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7086     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7087 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7088     if (mat->boundtocpu && mat->bindingpropagates) {
7089       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7090       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7091     }
7092 #endif
7093   }
7094   PetscFunctionReturn(PETSC_SUCCESS);
7095 }
7096 
7097 /*@C
7098   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7099 
7100   Collective
7101 
7102   Input Parameters:
7103 + mat   - the matrix
7104 . n     - the number of submatrixes to be extracted
7105 . irow  - index set of rows to extract
7106 . icol  - index set of columns to extract
7107 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7108 
7109   Output Parameter:
7110 . submat - the array of submatrices
7111 
7112   Level: advanced
7113 
7114   Note:
7115   This is used by `PCGASM`
7116 
7117 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7118 @*/
7119 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7120 {
7121   PetscInt  i;
7122   PetscBool eq;
7123 
7124   PetscFunctionBegin;
7125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7126   PetscValidType(mat, 1);
7127   if (n) {
7128     PetscAssertPointer(irow, 3);
7129     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7130     PetscAssertPointer(icol, 4);
7131     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7132   }
7133   PetscAssertPointer(submat, 6);
7134   if (n && scall == MAT_REUSE_MATRIX) {
7135     PetscAssertPointer(*submat, 6);
7136     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7137   }
7138   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7139   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7140   MatCheckPreallocated(mat, 1);
7141 
7142   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7143   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7144   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7145   for (i = 0; i < n; i++) {
7146     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7147     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7148   }
7149   PetscFunctionReturn(PETSC_SUCCESS);
7150 }
7151 
7152 /*@C
7153   MatDestroyMatrices - Destroys an array of matrices.
7154 
7155   Collective
7156 
7157   Input Parameters:
7158 + n   - the number of local matrices
7159 - mat - the matrices (this is a pointer to the array of matrices)
7160 
7161   Level: advanced
7162 
7163   Note:
7164   Frees not only the matrices, but also the array that contains the matrices
7165 
7166   Fortran Note:
7167   This does not free the array.
7168 
7169 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7170 @*/
7171 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7172 {
7173   PetscInt i;
7174 
7175   PetscFunctionBegin;
7176   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7177   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7178   PetscAssertPointer(mat, 2);
7179 
7180   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7181 
7182   /* memory is allocated even if n = 0 */
7183   PetscCall(PetscFree(*mat));
7184   PetscFunctionReturn(PETSC_SUCCESS);
7185 }
7186 
7187 /*@C
7188   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7189 
7190   Collective
7191 
7192   Input Parameters:
7193 + n   - the number of local matrices
7194 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7195                        sequence of `MatCreateSubMatrices()`)
7196 
7197   Level: advanced
7198 
7199   Note:
7200   Frees not only the matrices, but also the array that contains the matrices
7201 
7202   Fortran Note:
7203   This does not free the array.
7204 
7205 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7206 @*/
7207 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7208 {
7209   Mat mat0;
7210 
7211   PetscFunctionBegin;
7212   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7213   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7214   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7215   PetscAssertPointer(mat, 2);
7216 
7217   mat0 = (*mat)[0];
7218   if (mat0 && mat0->ops->destroysubmatrices) {
7219     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7220   } else {
7221     PetscCall(MatDestroyMatrices(n, mat));
7222   }
7223   PetscFunctionReturn(PETSC_SUCCESS);
7224 }
7225 
7226 /*@C
7227   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7228 
7229   Collective
7230 
7231   Input Parameter:
7232 . mat - the matrix
7233 
7234   Output Parameter:
7235 . matstruct - the sequential matrix with the nonzero structure of mat
7236 
7237   Level: developer
7238 
7239 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7240 @*/
7241 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7242 {
7243   PetscFunctionBegin;
7244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7245   PetscAssertPointer(matstruct, 2);
7246 
7247   PetscValidType(mat, 1);
7248   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7249   MatCheckPreallocated(mat, 1);
7250 
7251   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7252   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7253   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7254   PetscFunctionReturn(PETSC_SUCCESS);
7255 }
7256 
7257 /*@C
7258   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7259 
7260   Collective
7261 
7262   Input Parameter:
7263 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7264                        sequence of `MatGetSeqNonzeroStructure()`)
7265 
7266   Level: advanced
7267 
7268   Note:
7269   Frees not only the matrices, but also the array that contains the matrices
7270 
7271 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7272 @*/
7273 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7274 {
7275   PetscFunctionBegin;
7276   PetscAssertPointer(mat, 1);
7277   PetscCall(MatDestroy(mat));
7278   PetscFunctionReturn(PETSC_SUCCESS);
7279 }
7280 
7281 /*@
7282   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7283   replaces the index sets by larger ones that represent submatrices with
7284   additional overlap.
7285 
7286   Collective
7287 
7288   Input Parameters:
7289 + mat - the matrix
7290 . n   - the number of index sets
7291 . is  - the array of index sets (these index sets will changed during the call)
7292 - ov  - the additional overlap requested
7293 
7294   Options Database Key:
7295 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7296 
7297   Level: developer
7298 
7299   Note:
7300   The computed overlap preserves the matrix block sizes when the blocks are square.
7301   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7302   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7303 
7304 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7305 @*/
7306 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7307 {
7308   PetscInt i, bs, cbs;
7309 
7310   PetscFunctionBegin;
7311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7312   PetscValidType(mat, 1);
7313   PetscValidLogicalCollectiveInt(mat, n, 2);
7314   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7315   if (n) {
7316     PetscAssertPointer(is, 3);
7317     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7318   }
7319   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7320   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7321   MatCheckPreallocated(mat, 1);
7322 
7323   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7324   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7325   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7326   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7327   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7328   if (bs == cbs) {
7329     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7330   }
7331   PetscFunctionReturn(PETSC_SUCCESS);
7332 }
7333 
7334 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7335 
7336 /*@
7337   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7338   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7339   additional overlap.
7340 
7341   Collective
7342 
7343   Input Parameters:
7344 + mat - the matrix
7345 . n   - the number of index sets
7346 . is  - the array of index sets (these index sets will changed during the call)
7347 - ov  - the additional overlap requested
7348 
7349   `   Options Database Key:
7350 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7351 
7352   Level: developer
7353 
7354 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7355 @*/
7356 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7357 {
7358   PetscInt i;
7359 
7360   PetscFunctionBegin;
7361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7362   PetscValidType(mat, 1);
7363   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7364   if (n) {
7365     PetscAssertPointer(is, 3);
7366     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7367   }
7368   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7369   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7370   MatCheckPreallocated(mat, 1);
7371   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7372   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7373   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7374   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7375   PetscFunctionReturn(PETSC_SUCCESS);
7376 }
7377 
7378 /*@
7379   MatGetBlockSize - Returns the matrix block size.
7380 
7381   Not Collective
7382 
7383   Input Parameter:
7384 . mat - the matrix
7385 
7386   Output Parameter:
7387 . bs - block size
7388 
7389   Level: intermediate
7390 
7391   Notes:
7392   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7393 
7394   If the block size has not been set yet this routine returns 1.
7395 
7396 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7397 @*/
7398 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7399 {
7400   PetscFunctionBegin;
7401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7402   PetscAssertPointer(bs, 2);
7403   *bs = PetscAbs(mat->rmap->bs);
7404   PetscFunctionReturn(PETSC_SUCCESS);
7405 }
7406 
7407 /*@
7408   MatGetBlockSizes - Returns the matrix block row and column sizes.
7409 
7410   Not Collective
7411 
7412   Input Parameter:
7413 . mat - the matrix
7414 
7415   Output Parameters:
7416 + rbs - row block size
7417 - cbs - column block size
7418 
7419   Level: intermediate
7420 
7421   Notes:
7422   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7423   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7424 
7425   If a block size has not been set yet this routine returns 1.
7426 
7427 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7428 @*/
7429 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7430 {
7431   PetscFunctionBegin;
7432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7433   if (rbs) PetscAssertPointer(rbs, 2);
7434   if (cbs) PetscAssertPointer(cbs, 3);
7435   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7436   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7437   PetscFunctionReturn(PETSC_SUCCESS);
7438 }
7439 
7440 /*@
7441   MatSetBlockSize - Sets the matrix block size.
7442 
7443   Logically Collective
7444 
7445   Input Parameters:
7446 + mat - the matrix
7447 - bs  - block size
7448 
7449   Level: intermediate
7450 
7451   Notes:
7452   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7453   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7454 
7455   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7456   is compatible with the matrix local sizes.
7457 
7458 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7459 @*/
7460 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7461 {
7462   PetscFunctionBegin;
7463   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7464   PetscValidLogicalCollectiveInt(mat, bs, 2);
7465   PetscCall(MatSetBlockSizes(mat, bs, bs));
7466   PetscFunctionReturn(PETSC_SUCCESS);
7467 }
7468 
7469 typedef struct {
7470   PetscInt         n;
7471   IS              *is;
7472   Mat             *mat;
7473   PetscObjectState nonzerostate;
7474   Mat              C;
7475 } EnvelopeData;
7476 
7477 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7478 {
7479   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7480   PetscCall(PetscFree(edata->is));
7481   PetscCall(PetscFree(edata));
7482   return PETSC_SUCCESS;
7483 }
7484 
7485 /*@
7486   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7487   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7488 
7489   Collective
7490 
7491   Input Parameter:
7492 . mat - the matrix
7493 
7494   Level: intermediate
7495 
7496   Notes:
7497   There can be zeros within the blocks
7498 
7499   The blocks can overlap between processes, including laying on more than two processes
7500 
7501 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7502 @*/
7503 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7504 {
7505   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7506   PetscInt          *diag, *odiag, sc;
7507   VecScatter         scatter;
7508   PetscScalar       *seqv;
7509   const PetscScalar *parv;
7510   const PetscInt    *ia, *ja;
7511   PetscBool          set, flag, done;
7512   Mat                AA = mat, A;
7513   MPI_Comm           comm;
7514   PetscMPIInt        rank, size, tag;
7515   MPI_Status         status;
7516   PetscContainer     container;
7517   EnvelopeData      *edata;
7518   Vec                seq, par;
7519   IS                 isglobal;
7520 
7521   PetscFunctionBegin;
7522   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7523   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7524   if (!set || !flag) {
7525     /* TODO: only needs nonzero structure of transpose */
7526     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7527     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7528   }
7529   PetscCall(MatAIJGetLocalMat(AA, &A));
7530   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7531   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7532 
7533   PetscCall(MatGetLocalSize(mat, &n, NULL));
7534   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7535   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7536   PetscCallMPI(MPI_Comm_size(comm, &size));
7537   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7538 
7539   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7540 
7541   if (rank > 0) {
7542     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7543     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7544   }
7545   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7546   for (i = 0; i < n; i++) {
7547     env = PetscMax(env, ja[ia[i + 1] - 1]);
7548     II  = rstart + i;
7549     if (env == II) {
7550       starts[lblocks]  = tbs;
7551       sizes[lblocks++] = 1 + II - tbs;
7552       tbs              = 1 + II;
7553     }
7554   }
7555   if (rank < size - 1) {
7556     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7557     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7558   }
7559 
7560   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7561   if (!set || !flag) PetscCall(MatDestroy(&AA));
7562   PetscCall(MatDestroy(&A));
7563 
7564   PetscCall(PetscNew(&edata));
7565   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7566   edata->n = lblocks;
7567   /* create IS needed for extracting blocks from the original matrix */
7568   PetscCall(PetscMalloc1(lblocks, &edata->is));
7569   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7570 
7571   /* Create the resulting inverse matrix structure with preallocation information */
7572   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7573   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7574   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7575   PetscCall(MatSetType(edata->C, MATAIJ));
7576 
7577   /* Communicate the start and end of each row, from each block to the correct rank */
7578   /* TODO: Use PetscSF instead of VecScatter */
7579   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7580   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7581   PetscCall(VecGetArrayWrite(seq, &seqv));
7582   for (PetscInt i = 0; i < lblocks; i++) {
7583     for (PetscInt j = 0; j < sizes[i]; j++) {
7584       seqv[cnt]     = starts[i];
7585       seqv[cnt + 1] = starts[i] + sizes[i];
7586       cnt += 2;
7587     }
7588   }
7589   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7590   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7591   sc -= cnt;
7592   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7593   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7594   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7595   PetscCall(ISDestroy(&isglobal));
7596   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7597   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7598   PetscCall(VecScatterDestroy(&scatter));
7599   PetscCall(VecDestroy(&seq));
7600   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7601   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7602   PetscCall(VecGetArrayRead(par, &parv));
7603   cnt = 0;
7604   PetscCall(MatGetSize(mat, NULL, &n));
7605   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7606     PetscInt start, end, d = 0, od = 0;
7607 
7608     start = (PetscInt)PetscRealPart(parv[cnt]);
7609     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7610     cnt += 2;
7611 
7612     if (start < cstart) {
7613       od += cstart - start + n - cend;
7614       d += cend - cstart;
7615     } else if (start < cend) {
7616       od += n - cend;
7617       d += cend - start;
7618     } else od += n - start;
7619     if (end <= cstart) {
7620       od -= cstart - end + n - cend;
7621       d -= cend - cstart;
7622     } else if (end < cend) {
7623       od -= n - cend;
7624       d -= cend - end;
7625     } else od -= n - end;
7626 
7627     odiag[i] = od;
7628     diag[i]  = d;
7629   }
7630   PetscCall(VecRestoreArrayRead(par, &parv));
7631   PetscCall(VecDestroy(&par));
7632   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7633   PetscCall(PetscFree2(diag, odiag));
7634   PetscCall(PetscFree2(sizes, starts));
7635 
7636   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7637   PetscCall(PetscContainerSetPointer(container, edata));
7638   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7639   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7640   PetscCall(PetscObjectDereference((PetscObject)container));
7641   PetscFunctionReturn(PETSC_SUCCESS);
7642 }
7643 
7644 /*@
7645   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7646 
7647   Collective
7648 
7649   Input Parameters:
7650 + A     - the matrix
7651 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7652 
7653   Output Parameter:
7654 . C - matrix with inverted block diagonal of `A`
7655 
7656   Level: advanced
7657 
7658   Note:
7659   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7660 
7661 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7662 @*/
7663 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7664 {
7665   PetscContainer   container;
7666   EnvelopeData    *edata;
7667   PetscObjectState nonzerostate;
7668 
7669   PetscFunctionBegin;
7670   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7671   if (!container) {
7672     PetscCall(MatComputeVariableBlockEnvelope(A));
7673     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7674   }
7675   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7676   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7677   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7678   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7679 
7680   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7681   *C = edata->C;
7682 
7683   for (PetscInt i = 0; i < edata->n; i++) {
7684     Mat          D;
7685     PetscScalar *dvalues;
7686 
7687     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7688     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7689     PetscCall(MatSeqDenseInvert(D));
7690     PetscCall(MatDenseGetArray(D, &dvalues));
7691     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7692     PetscCall(MatDestroy(&D));
7693   }
7694   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7695   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7696   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7697   PetscFunctionReturn(PETSC_SUCCESS);
7698 }
7699 
7700 /*@
7701   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7702 
7703   Logically Collective
7704 
7705   Input Parameters:
7706 + mat     - the matrix
7707 . nblocks - the number of blocks on this process, each block can only exist on a single process
7708 - bsizes  - the block sizes
7709 
7710   Level: intermediate
7711 
7712   Notes:
7713   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7714 
7715   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.
7716 
7717 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7718           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7719 @*/
7720 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7721 {
7722   PetscInt i, ncnt = 0, nlocal;
7723 
7724   PetscFunctionBegin;
7725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7726   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7727   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7728   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7729   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);
7730   PetscCall(PetscFree(mat->bsizes));
7731   mat->nblocks = nblocks;
7732   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7733   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7734   PetscFunctionReturn(PETSC_SUCCESS);
7735 }
7736 
7737 /*@C
7738   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7739 
7740   Logically Collective; No Fortran Support
7741 
7742   Input Parameter:
7743 . mat - the matrix
7744 
7745   Output Parameters:
7746 + nblocks - the number of blocks on this process
7747 - bsizes  - the block sizes
7748 
7749   Level: intermediate
7750 
7751 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7752 @*/
7753 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7754 {
7755   PetscFunctionBegin;
7756   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7757   *nblocks = mat->nblocks;
7758   *bsizes  = mat->bsizes;
7759   PetscFunctionReturn(PETSC_SUCCESS);
7760 }
7761 
7762 /*@
7763   MatSetBlockSizes - Sets the matrix block row and column sizes.
7764 
7765   Logically Collective
7766 
7767   Input Parameters:
7768 + mat - the matrix
7769 . rbs - row block size
7770 - cbs - column block size
7771 
7772   Level: intermediate
7773 
7774   Notes:
7775   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7776   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7777   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7778 
7779   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7780   are compatible with the matrix local sizes.
7781 
7782   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7783 
7784 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7785 @*/
7786 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7787 {
7788   PetscFunctionBegin;
7789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7790   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7791   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7792   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7793   if (mat->rmap->refcnt) {
7794     ISLocalToGlobalMapping l2g  = NULL;
7795     PetscLayout            nmap = NULL;
7796 
7797     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7798     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7799     PetscCall(PetscLayoutDestroy(&mat->rmap));
7800     mat->rmap          = nmap;
7801     mat->rmap->mapping = l2g;
7802   }
7803   if (mat->cmap->refcnt) {
7804     ISLocalToGlobalMapping l2g  = NULL;
7805     PetscLayout            nmap = NULL;
7806 
7807     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7808     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7809     PetscCall(PetscLayoutDestroy(&mat->cmap));
7810     mat->cmap          = nmap;
7811     mat->cmap->mapping = l2g;
7812   }
7813   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7814   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7815   PetscFunctionReturn(PETSC_SUCCESS);
7816 }
7817 
7818 /*@
7819   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7820 
7821   Logically Collective
7822 
7823   Input Parameters:
7824 + mat     - the matrix
7825 . fromRow - matrix from which to copy row block size
7826 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7827 
7828   Level: developer
7829 
7830 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7831 @*/
7832 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7833 {
7834   PetscFunctionBegin;
7835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7836   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7837   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7838   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7839   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7840   PetscFunctionReturn(PETSC_SUCCESS);
7841 }
7842 
7843 /*@
7844   MatResidual - Default routine to calculate the residual r = b - Ax
7845 
7846   Collective
7847 
7848   Input Parameters:
7849 + mat - the matrix
7850 . b   - the right-hand-side
7851 - x   - the approximate solution
7852 
7853   Output Parameter:
7854 . r - location to store the residual
7855 
7856   Level: developer
7857 
7858 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7859 @*/
7860 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7861 {
7862   PetscFunctionBegin;
7863   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7864   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7865   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7866   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7867   PetscValidType(mat, 1);
7868   MatCheckPreallocated(mat, 1);
7869   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7870   if (!mat->ops->residual) {
7871     PetscCall(MatMult(mat, x, r));
7872     PetscCall(VecAYPX(r, -1.0, b));
7873   } else {
7874     PetscUseTypeMethod(mat, residual, b, x, r);
7875   }
7876   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7877   PetscFunctionReturn(PETSC_SUCCESS);
7878 }
7879 
7880 /*MC
7881     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7882 
7883     Synopsis:
7884     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7885 
7886     Not Collective
7887 
7888     Input Parameters:
7889 +   A - the matrix
7890 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7891 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7892 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7893                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7894                  always used.
7895 
7896     Output Parameters:
7897 +   n - number of local rows in the (possibly compressed) matrix
7898 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7899 .   ja - the column indices
7900 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7901            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7902 
7903     Level: developer
7904 
7905     Note:
7906     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7907 
7908 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7909 M*/
7910 
7911 /*MC
7912     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7913 
7914     Synopsis:
7915     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7916 
7917     Not Collective
7918 
7919     Input Parameters:
7920 +   A - the  matrix
7921 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7922 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7923     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7924                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7925                  always used.
7926 .   n - number of local rows in the (possibly compressed) matrix
7927 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7928 .   ja - the column indices
7929 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7930            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7931 
7932     Level: developer
7933 
7934 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7935 M*/
7936 
7937 /*@C
7938   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7939 
7940   Collective
7941 
7942   Input Parameters:
7943 + mat             - the matrix
7944 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7945 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7946 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7947                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7948                  always used.
7949 
7950   Output Parameters:
7951 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7952 . 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
7953 . ja   - the column indices, use `NULL` if not needed
7954 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7955            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7956 
7957   Level: developer
7958 
7959   Notes:
7960   You CANNOT change any of the ia[] or ja[] values.
7961 
7962   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7963 
7964   Fortran Notes:
7965   Use
7966 .vb
7967     PetscInt, pointer :: ia(:),ja(:)
7968     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7969     ! Access the ith and jth entries via ia(i) and ja(j)
7970 .ve
7971 
7972   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7973 
7974 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7975 @*/
7976 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7977 {
7978   PetscFunctionBegin;
7979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7980   PetscValidType(mat, 1);
7981   if (n) PetscAssertPointer(n, 5);
7982   if (ia) PetscAssertPointer(ia, 6);
7983   if (ja) PetscAssertPointer(ja, 7);
7984   if (done) PetscAssertPointer(done, 8);
7985   MatCheckPreallocated(mat, 1);
7986   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7987   else {
7988     if (done) *done = PETSC_TRUE;
7989     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7990     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7991     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7992   }
7993   PetscFunctionReturn(PETSC_SUCCESS);
7994 }
7995 
7996 /*@C
7997   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7998 
7999   Collective
8000 
8001   Input Parameters:
8002 + mat             - the matrix
8003 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8004 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8005                 symmetrized
8006 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8007                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8008                  always used.
8009 . n               - number of columns in the (possibly compressed) matrix
8010 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8011 - ja              - the row indices
8012 
8013   Output Parameter:
8014 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8015 
8016   Level: developer
8017 
8018 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8019 @*/
8020 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8021 {
8022   PetscFunctionBegin;
8023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8024   PetscValidType(mat, 1);
8025   PetscAssertPointer(n, 5);
8026   if (ia) PetscAssertPointer(ia, 6);
8027   if (ja) PetscAssertPointer(ja, 7);
8028   PetscAssertPointer(done, 8);
8029   MatCheckPreallocated(mat, 1);
8030   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8031   else {
8032     *done = PETSC_TRUE;
8033     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8034   }
8035   PetscFunctionReturn(PETSC_SUCCESS);
8036 }
8037 
8038 /*@C
8039   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8040 
8041   Collective
8042 
8043   Input Parameters:
8044 + mat             - the matrix
8045 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8046 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8047 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8048                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8049                  always used.
8050 . n               - size of (possibly compressed) matrix
8051 . ia              - the row pointers
8052 - ja              - the column indices
8053 
8054   Output Parameter:
8055 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8056 
8057   Level: developer
8058 
8059   Note:
8060   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8061   us of the array after it has been restored. If you pass `NULL`, it will
8062   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8063 
8064   Fortran Note:
8065   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8066 
8067 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8068 @*/
8069 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8070 {
8071   PetscFunctionBegin;
8072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8073   PetscValidType(mat, 1);
8074   if (ia) PetscAssertPointer(ia, 6);
8075   if (ja) PetscAssertPointer(ja, 7);
8076   if (done) PetscAssertPointer(done, 8);
8077   MatCheckPreallocated(mat, 1);
8078 
8079   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8080   else {
8081     if (done) *done = PETSC_TRUE;
8082     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8083     if (n) *n = 0;
8084     if (ia) *ia = NULL;
8085     if (ja) *ja = NULL;
8086   }
8087   PetscFunctionReturn(PETSC_SUCCESS);
8088 }
8089 
8090 /*@C
8091   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8092 
8093   Collective
8094 
8095   Input Parameters:
8096 + mat             - the matrix
8097 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8098 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8099 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8100                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8101                  always used.
8102 
8103   Output Parameters:
8104 + n    - size of (possibly compressed) matrix
8105 . ia   - the column pointers
8106 . ja   - the row indices
8107 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8108 
8109   Level: developer
8110 
8111 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8112 @*/
8113 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8114 {
8115   PetscFunctionBegin;
8116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8117   PetscValidType(mat, 1);
8118   if (ia) PetscAssertPointer(ia, 6);
8119   if (ja) PetscAssertPointer(ja, 7);
8120   PetscAssertPointer(done, 8);
8121   MatCheckPreallocated(mat, 1);
8122 
8123   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8124   else {
8125     *done = PETSC_TRUE;
8126     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8127     if (n) *n = 0;
8128     if (ia) *ia = NULL;
8129     if (ja) *ja = NULL;
8130   }
8131   PetscFunctionReturn(PETSC_SUCCESS);
8132 }
8133 
8134 /*@C
8135   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8136   `MatGetColumnIJ()`.
8137 
8138   Collective
8139 
8140   Input Parameters:
8141 + mat        - the matrix
8142 . ncolors    - maximum color value
8143 . n          - number of entries in colorarray
8144 - colorarray - array indicating color for each column
8145 
8146   Output Parameter:
8147 . iscoloring - coloring generated using colorarray information
8148 
8149   Level: developer
8150 
8151 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8152 @*/
8153 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8154 {
8155   PetscFunctionBegin;
8156   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8157   PetscValidType(mat, 1);
8158   PetscAssertPointer(colorarray, 4);
8159   PetscAssertPointer(iscoloring, 5);
8160   MatCheckPreallocated(mat, 1);
8161 
8162   if (!mat->ops->coloringpatch) {
8163     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8164   } else {
8165     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8166   }
8167   PetscFunctionReturn(PETSC_SUCCESS);
8168 }
8169 
8170 /*@
8171   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8172 
8173   Logically Collective
8174 
8175   Input Parameter:
8176 . mat - the factored matrix to be reset
8177 
8178   Level: developer
8179 
8180   Notes:
8181   This routine should be used only with factored matrices formed by in-place
8182   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8183   format).  This option can save memory, for example, when solving nonlinear
8184   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8185   ILU(0) preconditioner.
8186 
8187   One can specify in-place ILU(0) factorization by calling
8188 .vb
8189      PCType(pc,PCILU);
8190      PCFactorSeUseInPlace(pc);
8191 .ve
8192   or by using the options -pc_type ilu -pc_factor_in_place
8193 
8194   In-place factorization ILU(0) can also be used as a local
8195   solver for the blocks within the block Jacobi or additive Schwarz
8196   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8197   for details on setting local solver options.
8198 
8199   Most users should employ the `KSP` interface for linear solvers
8200   instead of working directly with matrix algebra routines such as this.
8201   See, e.g., `KSPCreate()`.
8202 
8203 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8204 @*/
8205 PetscErrorCode MatSetUnfactored(Mat mat)
8206 {
8207   PetscFunctionBegin;
8208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8209   PetscValidType(mat, 1);
8210   MatCheckPreallocated(mat, 1);
8211   mat->factortype = MAT_FACTOR_NONE;
8212   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8213   PetscUseTypeMethod(mat, setunfactored);
8214   PetscFunctionReturn(PETSC_SUCCESS);
8215 }
8216 
8217 /*MC
8218     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8219 
8220     Synopsis:
8221     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8222 
8223     Not Collective
8224 
8225     Input Parameter:
8226 .   x - matrix
8227 
8228     Output Parameters:
8229 +   xx_v - the Fortran pointer to the array
8230 -   ierr - error code
8231 
8232     Example of Usage:
8233 .vb
8234       PetscScalar, pointer xx_v(:,:)
8235       ....
8236       call MatDenseGetArrayF90(x,xx_v,ierr)
8237       a = xx_v(3)
8238       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8239 .ve
8240 
8241     Level: advanced
8242 
8243 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8244 M*/
8245 
8246 /*MC
8247     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8248     accessed with `MatDenseGetArrayF90()`.
8249 
8250     Synopsis:
8251     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8252 
8253     Not Collective
8254 
8255     Input Parameters:
8256 +   x - matrix
8257 -   xx_v - the Fortran90 pointer to the array
8258 
8259     Output Parameter:
8260 .   ierr - error code
8261 
8262     Example of Usage:
8263 .vb
8264        PetscScalar, pointer xx_v(:,:)
8265        ....
8266        call MatDenseGetArrayF90(x,xx_v,ierr)
8267        a = xx_v(3)
8268        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8269 .ve
8270 
8271     Level: advanced
8272 
8273 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8274 M*/
8275 
8276 /*MC
8277     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8278 
8279     Synopsis:
8280     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8281 
8282     Not Collective
8283 
8284     Input Parameter:
8285 .   x - matrix
8286 
8287     Output Parameters:
8288 +   xx_v - the Fortran pointer to the array
8289 -   ierr - error code
8290 
8291     Example of Usage:
8292 .vb
8293       PetscScalar, pointer xx_v(:)
8294       ....
8295       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8296       a = xx_v(3)
8297       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8298 .ve
8299 
8300     Level: advanced
8301 
8302 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8303 M*/
8304 
8305 /*MC
8306     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8307     accessed with `MatSeqAIJGetArrayF90()`.
8308 
8309     Synopsis:
8310     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8311 
8312     Not Collective
8313 
8314     Input Parameters:
8315 +   x - matrix
8316 -   xx_v - the Fortran90 pointer to the array
8317 
8318     Output Parameter:
8319 .   ierr - error code
8320 
8321     Example of Usage:
8322 .vb
8323        PetscScalar, pointer xx_v(:)
8324        ....
8325        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8326        a = xx_v(3)
8327        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8328 .ve
8329 
8330     Level: advanced
8331 
8332 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8333 M*/
8334 
8335 /*@
8336   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8337   as the original matrix.
8338 
8339   Collective
8340 
8341   Input Parameters:
8342 + mat   - the original matrix
8343 . isrow - parallel `IS` containing the rows this processor should obtain
8344 . 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.
8345 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8346 
8347   Output Parameter:
8348 . newmat - the new submatrix, of the same type as the original matrix
8349 
8350   Level: advanced
8351 
8352   Notes:
8353   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8354 
8355   Some matrix types place restrictions on the row and column indices, such
8356   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;
8357   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8358 
8359   The index sets may not have duplicate entries.
8360 
8361   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8362   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8363   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8364   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8365   you are finished using it.
8366 
8367   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8368   the input matrix.
8369 
8370   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8371 
8372   If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature
8373   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8374 
8375   Example usage:
8376   Consider the following 8x8 matrix with 34 non-zero values, that is
8377   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8378   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8379   as follows
8380 .vb
8381             1  2  0  |  0  3  0  |  0  4
8382     Proc0   0  5  6  |  7  0  0  |  8  0
8383             9  0 10  | 11  0  0  | 12  0
8384     -------------------------------------
8385            13  0 14  | 15 16 17  |  0  0
8386     Proc1   0 18  0  | 19 20 21  |  0  0
8387             0  0  0  | 22 23  0  | 24  0
8388     -------------------------------------
8389     Proc2  25 26 27  |  0  0 28  | 29  0
8390            30  0  0  | 31 32 33  |  0 34
8391 .ve
8392 
8393   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8394 
8395 .vb
8396             2  0  |  0  3  0  |  0
8397     Proc0   5  6  |  7  0  0  |  8
8398     -------------------------------
8399     Proc1  18  0  | 19 20 21  |  0
8400     -------------------------------
8401     Proc2  26 27  |  0  0 28  | 29
8402             0  0  | 31 32 33  |  0
8403 .ve
8404 
8405 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8406 @*/
8407 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8408 {
8409   PetscMPIInt size;
8410   Mat        *local;
8411   IS          iscoltmp;
8412   PetscBool   flg;
8413 
8414   PetscFunctionBegin;
8415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8416   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8417   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8418   PetscAssertPointer(newmat, 5);
8419   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8420   PetscValidType(mat, 1);
8421   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8422   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8423 
8424   MatCheckPreallocated(mat, 1);
8425   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8426 
8427   if (!iscol || isrow == iscol) {
8428     PetscBool   stride;
8429     PetscMPIInt grabentirematrix = 0, grab;
8430     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8431     if (stride) {
8432       PetscInt first, step, n, rstart, rend;
8433       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8434       if (step == 1) {
8435         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8436         if (rstart == first) {
8437           PetscCall(ISGetLocalSize(isrow, &n));
8438           if (n == rend - rstart) grabentirematrix = 1;
8439         }
8440       }
8441     }
8442     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8443     if (grab) {
8444       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8445       if (cll == MAT_INITIAL_MATRIX) {
8446         *newmat = mat;
8447         PetscCall(PetscObjectReference((PetscObject)mat));
8448       }
8449       PetscFunctionReturn(PETSC_SUCCESS);
8450     }
8451   }
8452 
8453   if (!iscol) {
8454     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8455   } else {
8456     iscoltmp = iscol;
8457   }
8458 
8459   /* if original matrix is on just one processor then use submatrix generated */
8460   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8461     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8462     goto setproperties;
8463   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8464     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8465     *newmat = *local;
8466     PetscCall(PetscFree(local));
8467     goto setproperties;
8468   } else if (!mat->ops->createsubmatrix) {
8469     /* Create a new matrix type that implements the operation using the full matrix */
8470     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8471     switch (cll) {
8472     case MAT_INITIAL_MATRIX:
8473       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8474       break;
8475     case MAT_REUSE_MATRIX:
8476       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8477       break;
8478     default:
8479       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8480     }
8481     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8482     goto setproperties;
8483   }
8484 
8485   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8486   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8487   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8488 
8489 setproperties:
8490   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8491   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8492   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8493   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8494   PetscFunctionReturn(PETSC_SUCCESS);
8495 }
8496 
8497 /*@
8498   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8499 
8500   Not Collective
8501 
8502   Input Parameters:
8503 + A - the matrix we wish to propagate options from
8504 - B - the matrix we wish to propagate options to
8505 
8506   Level: beginner
8507 
8508   Note:
8509   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8510 
8511 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8512 @*/
8513 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8514 {
8515   PetscFunctionBegin;
8516   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8517   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8518   B->symmetry_eternal            = A->symmetry_eternal;
8519   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8520   B->symmetric                   = A->symmetric;
8521   B->structurally_symmetric      = A->structurally_symmetric;
8522   B->spd                         = A->spd;
8523   B->hermitian                   = A->hermitian;
8524   PetscFunctionReturn(PETSC_SUCCESS);
8525 }
8526 
8527 /*@
8528   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8529   used during the assembly process to store values that belong to
8530   other processors.
8531 
8532   Not Collective
8533 
8534   Input Parameters:
8535 + mat   - the matrix
8536 . size  - the initial size of the stash.
8537 - bsize - the initial size of the block-stash(if used).
8538 
8539   Options Database Keys:
8540 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8541 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8542 
8543   Level: intermediate
8544 
8545   Notes:
8546   The block-stash is used for values set with `MatSetValuesBlocked()` while
8547   the stash is used for values set with `MatSetValues()`
8548 
8549   Run with the option -info and look for output of the form
8550   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8551   to determine the appropriate value, MM, to use for size and
8552   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8553   to determine the value, BMM to use for bsize
8554 
8555 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8556 @*/
8557 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8558 {
8559   PetscFunctionBegin;
8560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8561   PetscValidType(mat, 1);
8562   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8563   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8564   PetscFunctionReturn(PETSC_SUCCESS);
8565 }
8566 
8567 /*@
8568   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8569   the matrix
8570 
8571   Neighbor-wise Collective
8572 
8573   Input Parameters:
8574 + A - the matrix
8575 . x - the vector to be multiplied by the interpolation operator
8576 - y - the vector to be added to the result
8577 
8578   Output Parameter:
8579 . w - the resulting vector
8580 
8581   Level: intermediate
8582 
8583   Notes:
8584   `w` may be the same vector as `y`.
8585 
8586   This allows one to use either the restriction or interpolation (its transpose)
8587   matrix to do the interpolation
8588 
8589 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8590 @*/
8591 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8592 {
8593   PetscInt M, N, Ny;
8594 
8595   PetscFunctionBegin;
8596   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8597   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8598   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8599   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8600   PetscCall(MatGetSize(A, &M, &N));
8601   PetscCall(VecGetSize(y, &Ny));
8602   if (M == Ny) {
8603     PetscCall(MatMultAdd(A, x, y, w));
8604   } else {
8605     PetscCall(MatMultTransposeAdd(A, x, y, w));
8606   }
8607   PetscFunctionReturn(PETSC_SUCCESS);
8608 }
8609 
8610 /*@
8611   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8612   the matrix
8613 
8614   Neighbor-wise Collective
8615 
8616   Input Parameters:
8617 + A - the matrix
8618 - x - the vector to be interpolated
8619 
8620   Output Parameter:
8621 . y - the resulting vector
8622 
8623   Level: intermediate
8624 
8625   Note:
8626   This allows one to use either the restriction or interpolation (its transpose)
8627   matrix to do the interpolation
8628 
8629 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8630 @*/
8631 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8632 {
8633   PetscInt M, N, Ny;
8634 
8635   PetscFunctionBegin;
8636   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8637   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8638   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8639   PetscCall(MatGetSize(A, &M, &N));
8640   PetscCall(VecGetSize(y, &Ny));
8641   if (M == Ny) {
8642     PetscCall(MatMult(A, x, y));
8643   } else {
8644     PetscCall(MatMultTranspose(A, x, y));
8645   }
8646   PetscFunctionReturn(PETSC_SUCCESS);
8647 }
8648 
8649 /*@
8650   MatRestrict - $y = A*x$ or $A^T*x$
8651 
8652   Neighbor-wise Collective
8653 
8654   Input Parameters:
8655 + A - the matrix
8656 - x - the vector to be restricted
8657 
8658   Output Parameter:
8659 . y - the resulting vector
8660 
8661   Level: intermediate
8662 
8663   Note:
8664   This allows one to use either the restriction or interpolation (its transpose)
8665   matrix to do the restriction
8666 
8667 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8668 @*/
8669 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8670 {
8671   PetscInt M, N, Ny;
8672 
8673   PetscFunctionBegin;
8674   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8675   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8676   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8677   PetscCall(MatGetSize(A, &M, &N));
8678   PetscCall(VecGetSize(y, &Ny));
8679   if (M == Ny) {
8680     PetscCall(MatMult(A, x, y));
8681   } else {
8682     PetscCall(MatMultTranspose(A, x, y));
8683   }
8684   PetscFunctionReturn(PETSC_SUCCESS);
8685 }
8686 
8687 /*@
8688   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8689 
8690   Neighbor-wise Collective
8691 
8692   Input Parameters:
8693 + A - the matrix
8694 . x - the input dense matrix to be multiplied
8695 - w - the input dense matrix to be added to the result
8696 
8697   Output Parameter:
8698 . y - the output dense matrix
8699 
8700   Level: intermediate
8701 
8702   Note:
8703   This allows one to use either the restriction or interpolation (its transpose)
8704   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8705   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8706 
8707 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8708 @*/
8709 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8710 {
8711   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8712   PetscBool trans = PETSC_TRUE;
8713   MatReuse  reuse = MAT_INITIAL_MATRIX;
8714 
8715   PetscFunctionBegin;
8716   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8717   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8718   PetscValidType(x, 2);
8719   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8720   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8721   PetscCall(MatGetSize(A, &M, &N));
8722   PetscCall(MatGetSize(x, &Mx, &Nx));
8723   if (N == Mx) trans = PETSC_FALSE;
8724   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);
8725   Mo = trans ? N : M;
8726   if (*y) {
8727     PetscCall(MatGetSize(*y, &My, &Ny));
8728     if (Mo == My && Nx == Ny) {
8729       reuse = MAT_REUSE_MATRIX;
8730     } else {
8731       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);
8732       PetscCall(MatDestroy(y));
8733     }
8734   }
8735 
8736   if (w && *y == w) { /* this is to minimize changes in PCMG */
8737     PetscBool flg;
8738 
8739     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8740     if (w) {
8741       PetscInt My, Ny, Mw, Nw;
8742 
8743       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8744       PetscCall(MatGetSize(*y, &My, &Ny));
8745       PetscCall(MatGetSize(w, &Mw, &Nw));
8746       if (!flg || My != Mw || Ny != Nw) w = NULL;
8747     }
8748     if (!w) {
8749       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8750       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8751       PetscCall(PetscObjectDereference((PetscObject)w));
8752     } else {
8753       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8754     }
8755   }
8756   if (!trans) {
8757     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8758   } else {
8759     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8760   }
8761   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8762   PetscFunctionReturn(PETSC_SUCCESS);
8763 }
8764 
8765 /*@
8766   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8767 
8768   Neighbor-wise Collective
8769 
8770   Input Parameters:
8771 + A - the matrix
8772 - x - the input dense matrix
8773 
8774   Output Parameter:
8775 . y - the output dense matrix
8776 
8777   Level: intermediate
8778 
8779   Note:
8780   This allows one to use either the restriction or interpolation (its transpose)
8781   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8782   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8783 
8784 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8785 @*/
8786 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8787 {
8788   PetscFunctionBegin;
8789   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8790   PetscFunctionReturn(PETSC_SUCCESS);
8791 }
8792 
8793 /*@
8794   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8795 
8796   Neighbor-wise Collective
8797 
8798   Input Parameters:
8799 + A - the matrix
8800 - x - the input dense matrix
8801 
8802   Output Parameter:
8803 . y - the output dense matrix
8804 
8805   Level: intermediate
8806 
8807   Note:
8808   This allows one to use either the restriction or interpolation (its transpose)
8809   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8810   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8811 
8812 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8813 @*/
8814 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8815 {
8816   PetscFunctionBegin;
8817   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8818   PetscFunctionReturn(PETSC_SUCCESS);
8819 }
8820 
8821 /*@
8822   MatGetNullSpace - retrieves the null space of a matrix.
8823 
8824   Logically Collective
8825 
8826   Input Parameters:
8827 + mat    - the matrix
8828 - nullsp - the null space object
8829 
8830   Level: developer
8831 
8832 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8833 @*/
8834 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8835 {
8836   PetscFunctionBegin;
8837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8838   PetscAssertPointer(nullsp, 2);
8839   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8840   PetscFunctionReturn(PETSC_SUCCESS);
8841 }
8842 
8843 /*@
8844   MatSetNullSpace - attaches a null space to a matrix.
8845 
8846   Logically Collective
8847 
8848   Input Parameters:
8849 + mat    - the matrix
8850 - nullsp - the null space object
8851 
8852   Level: advanced
8853 
8854   Notes:
8855   This null space is used by the `KSP` linear solvers to solve singular systems.
8856 
8857   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`
8858 
8859   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
8860   to zero but the linear system will still be solved in a least squares sense.
8861 
8862   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8863   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)$.
8864   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
8865   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
8866   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$).
8867   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8868 
8869   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8870   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8871   routine also automatically calls `MatSetTransposeNullSpace()`.
8872 
8873   The user should call `MatNullSpaceDestroy()`.
8874 
8875 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8876           `KSPSetPCSide()`
8877 @*/
8878 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8879 {
8880   PetscFunctionBegin;
8881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8882   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8883   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8884   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8885   mat->nullsp = nullsp;
8886   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8887   PetscFunctionReturn(PETSC_SUCCESS);
8888 }
8889 
8890 /*@
8891   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8892 
8893   Logically Collective
8894 
8895   Input Parameters:
8896 + mat    - the matrix
8897 - nullsp - the null space object
8898 
8899   Level: developer
8900 
8901 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8902 @*/
8903 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8904 {
8905   PetscFunctionBegin;
8906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8907   PetscValidType(mat, 1);
8908   PetscAssertPointer(nullsp, 2);
8909   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8910   PetscFunctionReturn(PETSC_SUCCESS);
8911 }
8912 
8913 /*@
8914   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8915 
8916   Logically Collective
8917 
8918   Input Parameters:
8919 + mat    - the matrix
8920 - nullsp - the null space object
8921 
8922   Level: advanced
8923 
8924   Notes:
8925   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8926 
8927   See `MatSetNullSpace()`
8928 
8929 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8930 @*/
8931 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8932 {
8933   PetscFunctionBegin;
8934   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8935   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8936   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8937   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8938   mat->transnullsp = nullsp;
8939   PetscFunctionReturn(PETSC_SUCCESS);
8940 }
8941 
8942 /*@
8943   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8944   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8945 
8946   Logically Collective
8947 
8948   Input Parameters:
8949 + mat    - the matrix
8950 - nullsp - the null space object
8951 
8952   Level: advanced
8953 
8954   Notes:
8955   Overwrites any previous near null space that may have been attached
8956 
8957   You can remove the null space by calling this routine with an `nullsp` of `NULL`
8958 
8959 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8960 @*/
8961 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8962 {
8963   PetscFunctionBegin;
8964   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8965   PetscValidType(mat, 1);
8966   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8967   MatCheckPreallocated(mat, 1);
8968   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8969   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8970   mat->nearnullsp = nullsp;
8971   PetscFunctionReturn(PETSC_SUCCESS);
8972 }
8973 
8974 /*@
8975   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8976 
8977   Not Collective
8978 
8979   Input Parameter:
8980 . mat - the matrix
8981 
8982   Output Parameter:
8983 . nullsp - the null space object, `NULL` if not set
8984 
8985   Level: advanced
8986 
8987 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8988 @*/
8989 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8990 {
8991   PetscFunctionBegin;
8992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8993   PetscValidType(mat, 1);
8994   PetscAssertPointer(nullsp, 2);
8995   MatCheckPreallocated(mat, 1);
8996   *nullsp = mat->nearnullsp;
8997   PetscFunctionReturn(PETSC_SUCCESS);
8998 }
8999 
9000 /*@C
9001   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9002 
9003   Collective
9004 
9005   Input Parameters:
9006 + mat  - the matrix
9007 . row  - row/column permutation
9008 - info - information on desired factorization process
9009 
9010   Level: developer
9011 
9012   Notes:
9013   Probably really in-place only when level of fill is zero, otherwise allocates
9014   new space to store factored matrix and deletes previous memory.
9015 
9016   Most users should employ the `KSP` interface for linear solvers
9017   instead of working directly with matrix algebra routines such as this.
9018   See, e.g., `KSPCreate()`.
9019 
9020   Developer Note:
9021   The Fortran interface is not autogenerated as the
9022   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9023 
9024 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9025 @*/
9026 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9027 {
9028   PetscFunctionBegin;
9029   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9030   PetscValidType(mat, 1);
9031   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9032   PetscAssertPointer(info, 3);
9033   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9034   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9035   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9036   MatCheckPreallocated(mat, 1);
9037   PetscUseTypeMethod(mat, iccfactor, row, info);
9038   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9039   PetscFunctionReturn(PETSC_SUCCESS);
9040 }
9041 
9042 /*@
9043   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9044   ghosted ones.
9045 
9046   Not Collective
9047 
9048   Input Parameters:
9049 + mat  - the matrix
9050 - diag - the diagonal values, including ghost ones
9051 
9052   Level: developer
9053 
9054   Notes:
9055   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9056 
9057   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9058 
9059 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9060 @*/
9061 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9062 {
9063   PetscMPIInt size;
9064 
9065   PetscFunctionBegin;
9066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9067   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9068   PetscValidType(mat, 1);
9069 
9070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9071   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9072   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9073   if (size == 1) {
9074     PetscInt n, m;
9075     PetscCall(VecGetSize(diag, &n));
9076     PetscCall(MatGetSize(mat, NULL, &m));
9077     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9078     PetscCall(MatDiagonalScale(mat, NULL, diag));
9079   } else {
9080     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9081   }
9082   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9083   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9084   PetscFunctionReturn(PETSC_SUCCESS);
9085 }
9086 
9087 /*@
9088   MatGetInertia - Gets the inertia from a factored matrix
9089 
9090   Collective
9091 
9092   Input Parameter:
9093 . mat - the matrix
9094 
9095   Output Parameters:
9096 + nneg  - number of negative eigenvalues
9097 . nzero - number of zero eigenvalues
9098 - npos  - number of positive eigenvalues
9099 
9100   Level: advanced
9101 
9102   Note:
9103   Matrix must have been factored by `MatCholeskyFactor()`
9104 
9105 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9106 @*/
9107 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9108 {
9109   PetscFunctionBegin;
9110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9111   PetscValidType(mat, 1);
9112   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9113   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9114   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9115   PetscFunctionReturn(PETSC_SUCCESS);
9116 }
9117 
9118 /*@C
9119   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9120 
9121   Neighbor-wise Collective
9122 
9123   Input Parameters:
9124 + mat - the factored matrix obtained with `MatGetFactor()`
9125 - b   - the right-hand-side vectors
9126 
9127   Output Parameter:
9128 . x - the result vectors
9129 
9130   Level: developer
9131 
9132   Note:
9133   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9134   call `MatSolves`(A,x,x).
9135 
9136 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9137 @*/
9138 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9139 {
9140   PetscFunctionBegin;
9141   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9142   PetscValidType(mat, 1);
9143   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9144   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9145   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9146 
9147   MatCheckPreallocated(mat, 1);
9148   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9149   PetscUseTypeMethod(mat, solves, b, x);
9150   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9151   PetscFunctionReturn(PETSC_SUCCESS);
9152 }
9153 
9154 /*@
9155   MatIsSymmetric - Test whether a matrix is symmetric
9156 
9157   Collective
9158 
9159   Input Parameters:
9160 + A   - the matrix to test
9161 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9162 
9163   Output Parameter:
9164 . flg - the result
9165 
9166   Level: intermediate
9167 
9168   Notes:
9169   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9170 
9171   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9172 
9173   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9174   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9175 
9176 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9177           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9178 @*/
9179 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9180 {
9181   PetscFunctionBegin;
9182   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9183   PetscAssertPointer(flg, 3);
9184 
9185   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9186   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9187   else {
9188     PetscUseTypeMethod(A, issymmetric, tol, flg);
9189     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9190   }
9191   PetscFunctionReturn(PETSC_SUCCESS);
9192 }
9193 
9194 /*@
9195   MatIsHermitian - Test whether a matrix is Hermitian
9196 
9197   Collective
9198 
9199   Input Parameters:
9200 + A   - the matrix to test
9201 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9202 
9203   Output Parameter:
9204 . flg - the result
9205 
9206   Level: intermediate
9207 
9208   Notes:
9209   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9210 
9211   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9212 
9213   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9214   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9215 
9216 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9217           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9218 @*/
9219 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9220 {
9221   PetscFunctionBegin;
9222   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9223   PetscAssertPointer(flg, 3);
9224 
9225   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9226   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9227   else {
9228     PetscUseTypeMethod(A, ishermitian, tol, flg);
9229     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9230   }
9231   PetscFunctionReturn(PETSC_SUCCESS);
9232 }
9233 
9234 /*@
9235   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9236 
9237   Not Collective
9238 
9239   Input Parameter:
9240 . A - the matrix to check
9241 
9242   Output Parameters:
9243 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9244 - flg - the result (only valid if set is `PETSC_TRUE`)
9245 
9246   Level: advanced
9247 
9248   Notes:
9249   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9250   if you want it explicitly checked
9251 
9252   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9253   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9254 
9255 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9256 @*/
9257 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9258 {
9259   PetscFunctionBegin;
9260   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9261   PetscAssertPointer(set, 2);
9262   PetscAssertPointer(flg, 3);
9263   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9264     *set = PETSC_TRUE;
9265     *flg = PetscBool3ToBool(A->symmetric);
9266   } else {
9267     *set = PETSC_FALSE;
9268   }
9269   PetscFunctionReturn(PETSC_SUCCESS);
9270 }
9271 
9272 /*@
9273   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9274 
9275   Not Collective
9276 
9277   Input Parameter:
9278 . A - the matrix to check
9279 
9280   Output Parameters:
9281 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9282 - flg - the result (only valid if set is `PETSC_TRUE`)
9283 
9284   Level: advanced
9285 
9286   Notes:
9287   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9288 
9289   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9290   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9291 
9292 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9293 @*/
9294 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9295 {
9296   PetscFunctionBegin;
9297   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9298   PetscAssertPointer(set, 2);
9299   PetscAssertPointer(flg, 3);
9300   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9301     *set = PETSC_TRUE;
9302     *flg = PetscBool3ToBool(A->spd);
9303   } else {
9304     *set = PETSC_FALSE;
9305   }
9306   PetscFunctionReturn(PETSC_SUCCESS);
9307 }
9308 
9309 /*@
9310   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9311 
9312   Not Collective
9313 
9314   Input Parameter:
9315 . A - the matrix to check
9316 
9317   Output Parameters:
9318 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9319 - flg - the result (only valid if set is `PETSC_TRUE`)
9320 
9321   Level: advanced
9322 
9323   Notes:
9324   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9325   if you want it explicitly checked
9326 
9327   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9328   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9329 
9330 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9331 @*/
9332 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9333 {
9334   PetscFunctionBegin;
9335   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9336   PetscAssertPointer(set, 2);
9337   PetscAssertPointer(flg, 3);
9338   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9339     *set = PETSC_TRUE;
9340     *flg = PetscBool3ToBool(A->hermitian);
9341   } else {
9342     *set = PETSC_FALSE;
9343   }
9344   PetscFunctionReturn(PETSC_SUCCESS);
9345 }
9346 
9347 /*@
9348   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9349 
9350   Collective
9351 
9352   Input Parameter:
9353 . A - the matrix to test
9354 
9355   Output Parameter:
9356 . flg - the result
9357 
9358   Level: intermediate
9359 
9360   Notes:
9361   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9362 
9363   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
9364   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9365 
9366 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9367 @*/
9368 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9369 {
9370   PetscFunctionBegin;
9371   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9372   PetscAssertPointer(flg, 2);
9373   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9374     *flg = PetscBool3ToBool(A->structurally_symmetric);
9375   } else {
9376     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9377     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9378   }
9379   PetscFunctionReturn(PETSC_SUCCESS);
9380 }
9381 
9382 /*@
9383   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9384 
9385   Not Collective
9386 
9387   Input Parameter:
9388 . A - the matrix to check
9389 
9390   Output Parameters:
9391 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9392 - flg - the result (only valid if set is PETSC_TRUE)
9393 
9394   Level: advanced
9395 
9396   Notes:
9397   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
9398   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9399 
9400   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9401 
9402 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9403 @*/
9404 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9405 {
9406   PetscFunctionBegin;
9407   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9408   PetscAssertPointer(set, 2);
9409   PetscAssertPointer(flg, 3);
9410   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9411     *set = PETSC_TRUE;
9412     *flg = PetscBool3ToBool(A->structurally_symmetric);
9413   } else {
9414     *set = PETSC_FALSE;
9415   }
9416   PetscFunctionReturn(PETSC_SUCCESS);
9417 }
9418 
9419 /*@
9420   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9421   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9422 
9423   Not Collective
9424 
9425   Input Parameter:
9426 . mat - the matrix
9427 
9428   Output Parameters:
9429 + nstash    - the size of the stash
9430 . reallocs  - the number of additional mallocs incurred.
9431 . bnstash   - the size of the block stash
9432 - breallocs - the number of additional mallocs incurred.in the block stash
9433 
9434   Level: advanced
9435 
9436 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9437 @*/
9438 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9439 {
9440   PetscFunctionBegin;
9441   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9442   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9443   PetscFunctionReturn(PETSC_SUCCESS);
9444 }
9445 
9446 /*@C
9447   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9448   parallel layout, `PetscLayout` for rows and columns
9449 
9450   Collective
9451 
9452   Input Parameter:
9453 . mat - the matrix
9454 
9455   Output Parameters:
9456 + right - (optional) vector that the matrix can be multiplied against
9457 - left  - (optional) vector that the matrix vector product can be stored in
9458 
9459   Level: advanced
9460 
9461   Notes:
9462   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()`.
9463 
9464   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9465 
9466 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9467 @*/
9468 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9469 {
9470   PetscFunctionBegin;
9471   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9472   PetscValidType(mat, 1);
9473   if (mat->ops->getvecs) {
9474     PetscUseTypeMethod(mat, getvecs, right, left);
9475   } else {
9476     if (right) {
9477       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9478       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9479       PetscCall(VecSetType(*right, 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(*right, PETSC_TRUE));
9483         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9484       }
9485 #endif
9486     }
9487     if (left) {
9488       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9489       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9490       PetscCall(VecSetType(*left, mat->defaultvectype));
9491 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9492       if (mat->boundtocpu && mat->bindingpropagates) {
9493         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9494         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9495       }
9496 #endif
9497     }
9498   }
9499   PetscFunctionReturn(PETSC_SUCCESS);
9500 }
9501 
9502 /*@C
9503   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9504   with default values.
9505 
9506   Not Collective
9507 
9508   Input Parameter:
9509 . info - the `MatFactorInfo` data structure
9510 
9511   Level: developer
9512 
9513   Notes:
9514   The solvers are generally used through the `KSP` and `PC` objects, for example
9515   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9516 
9517   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9518 
9519   Developer Note:
9520   The Fortran interface is not autogenerated as the
9521   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9522 
9523 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9524 @*/
9525 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9526 {
9527   PetscFunctionBegin;
9528   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9529   PetscFunctionReturn(PETSC_SUCCESS);
9530 }
9531 
9532 /*@
9533   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9534 
9535   Collective
9536 
9537   Input Parameters:
9538 + mat - the factored matrix
9539 - is  - the index set defining the Schur indices (0-based)
9540 
9541   Level: advanced
9542 
9543   Notes:
9544   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9545 
9546   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9547 
9548   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9549 
9550 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9551           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9552 @*/
9553 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9554 {
9555   PetscErrorCode (*f)(Mat, IS);
9556 
9557   PetscFunctionBegin;
9558   PetscValidType(mat, 1);
9559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9560   PetscValidType(is, 2);
9561   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9562   PetscCheckSameComm(mat, 1, is, 2);
9563   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9564   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9565   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9566   PetscCall(MatDestroy(&mat->schur));
9567   PetscCall((*f)(mat, is));
9568   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9569   PetscFunctionReturn(PETSC_SUCCESS);
9570 }
9571 
9572 /*@
9573   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9574 
9575   Logically Collective
9576 
9577   Input Parameters:
9578 + F      - the factored matrix obtained by calling `MatGetFactor()`
9579 . S      - location where to return the Schur complement, can be `NULL`
9580 - status - the status of the Schur complement matrix, can be `NULL`
9581 
9582   Level: advanced
9583 
9584   Notes:
9585   You must call `MatFactorSetSchurIS()` before calling this routine.
9586 
9587   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9588 
9589   The routine provides a copy of the Schur matrix stored within the solver data structures.
9590   The caller must destroy the object when it is no longer needed.
9591   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9592 
9593   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)
9594 
9595   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9596 
9597   Developer Note:
9598   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9599   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9600 
9601 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9602 @*/
9603 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9604 {
9605   PetscFunctionBegin;
9606   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9607   if (S) PetscAssertPointer(S, 2);
9608   if (status) PetscAssertPointer(status, 3);
9609   if (S) {
9610     PetscErrorCode (*f)(Mat, Mat *);
9611 
9612     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9613     if (f) {
9614       PetscCall((*f)(F, S));
9615     } else {
9616       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9617     }
9618   }
9619   if (status) *status = F->schur_status;
9620   PetscFunctionReturn(PETSC_SUCCESS);
9621 }
9622 
9623 /*@
9624   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9625 
9626   Logically Collective
9627 
9628   Input Parameters:
9629 + F      - the factored matrix obtained by calling `MatGetFactor()`
9630 . S      - location where to return the Schur complement, can be `NULL`
9631 - status - the status of the Schur complement matrix, can be `NULL`
9632 
9633   Level: advanced
9634 
9635   Notes:
9636   You must call `MatFactorSetSchurIS()` before calling this routine.
9637 
9638   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9639 
9640   The routine returns a the Schur Complement stored within the data structures of the solver.
9641 
9642   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9643 
9644   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9645 
9646   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9647 
9648   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9649 
9650 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9651 @*/
9652 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9653 {
9654   PetscFunctionBegin;
9655   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9656   if (S) {
9657     PetscAssertPointer(S, 2);
9658     *S = F->schur;
9659   }
9660   if (status) {
9661     PetscAssertPointer(status, 3);
9662     *status = F->schur_status;
9663   }
9664   PetscFunctionReturn(PETSC_SUCCESS);
9665 }
9666 
9667 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9668 {
9669   Mat S = F->schur;
9670 
9671   PetscFunctionBegin;
9672   switch (F->schur_status) {
9673   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9674   case MAT_FACTOR_SCHUR_INVERTED:
9675     if (S) {
9676       S->ops->solve             = NULL;
9677       S->ops->matsolve          = NULL;
9678       S->ops->solvetranspose    = NULL;
9679       S->ops->matsolvetranspose = NULL;
9680       S->ops->solveadd          = NULL;
9681       S->ops->solvetransposeadd = NULL;
9682       S->factortype             = MAT_FACTOR_NONE;
9683       PetscCall(PetscFree(S->solvertype));
9684     }
9685   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9686     break;
9687   default:
9688     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9689   }
9690   PetscFunctionReturn(PETSC_SUCCESS);
9691 }
9692 
9693 /*@
9694   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9695 
9696   Logically Collective
9697 
9698   Input Parameters:
9699 + F      - the factored matrix obtained by calling `MatGetFactor()`
9700 . S      - location where the Schur complement is stored
9701 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9702 
9703   Level: advanced
9704 
9705 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9706 @*/
9707 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9708 {
9709   PetscFunctionBegin;
9710   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9711   if (S) {
9712     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9713     *S = NULL;
9714   }
9715   F->schur_status = status;
9716   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9717   PetscFunctionReturn(PETSC_SUCCESS);
9718 }
9719 
9720 /*@
9721   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9722 
9723   Logically Collective
9724 
9725   Input Parameters:
9726 + F   - the factored matrix obtained by calling `MatGetFactor()`
9727 . rhs - location where the right hand side of the Schur complement system is stored
9728 - sol - location where the solution of the Schur complement system has to be returned
9729 
9730   Level: advanced
9731 
9732   Notes:
9733   The sizes of the vectors should match the size of the Schur complement
9734 
9735   Must be called after `MatFactorSetSchurIS()`
9736 
9737 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9738 @*/
9739 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9740 {
9741   PetscFunctionBegin;
9742   PetscValidType(F, 1);
9743   PetscValidType(rhs, 2);
9744   PetscValidType(sol, 3);
9745   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9746   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9747   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9748   PetscCheckSameComm(F, 1, rhs, 2);
9749   PetscCheckSameComm(F, 1, sol, 3);
9750   PetscCall(MatFactorFactorizeSchurComplement(F));
9751   switch (F->schur_status) {
9752   case MAT_FACTOR_SCHUR_FACTORED:
9753     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9754     break;
9755   case MAT_FACTOR_SCHUR_INVERTED:
9756     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9757     break;
9758   default:
9759     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9760   }
9761   PetscFunctionReturn(PETSC_SUCCESS);
9762 }
9763 
9764 /*@
9765   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9766 
9767   Logically Collective
9768 
9769   Input Parameters:
9770 + F   - the factored matrix obtained by calling `MatGetFactor()`
9771 . rhs - location where the right hand side of the Schur complement system is stored
9772 - sol - location where the solution of the Schur complement system has to be returned
9773 
9774   Level: advanced
9775 
9776   Notes:
9777   The sizes of the vectors should match the size of the Schur complement
9778 
9779   Must be called after `MatFactorSetSchurIS()`
9780 
9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9782 @*/
9783 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9784 {
9785   PetscFunctionBegin;
9786   PetscValidType(F, 1);
9787   PetscValidType(rhs, 2);
9788   PetscValidType(sol, 3);
9789   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9790   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9791   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9792   PetscCheckSameComm(F, 1, rhs, 2);
9793   PetscCheckSameComm(F, 1, sol, 3);
9794   PetscCall(MatFactorFactorizeSchurComplement(F));
9795   switch (F->schur_status) {
9796   case MAT_FACTOR_SCHUR_FACTORED:
9797     PetscCall(MatSolve(F->schur, rhs, sol));
9798     break;
9799   case MAT_FACTOR_SCHUR_INVERTED:
9800     PetscCall(MatMult(F->schur, rhs, sol));
9801     break;
9802   default:
9803     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9804   }
9805   PetscFunctionReturn(PETSC_SUCCESS);
9806 }
9807 
9808 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9809 #if PetscDefined(HAVE_CUDA)
9810 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9811 #endif
9812 
9813 /* Schur status updated in the interface */
9814 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9815 {
9816   Mat S = F->schur;
9817 
9818   PetscFunctionBegin;
9819   if (S) {
9820     PetscMPIInt size;
9821     PetscBool   isdense, isdensecuda;
9822 
9823     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9824     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9825     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9826     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9827     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9828     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9829     if (isdense) {
9830       PetscCall(MatSeqDenseInvertFactors_Private(S));
9831     } else if (isdensecuda) {
9832 #if defined(PETSC_HAVE_CUDA)
9833       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9834 #endif
9835     }
9836     // HIP??????????????
9837     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9838   }
9839   PetscFunctionReturn(PETSC_SUCCESS);
9840 }
9841 
9842 /*@
9843   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9844 
9845   Logically Collective
9846 
9847   Input Parameter:
9848 . F - the factored matrix obtained by calling `MatGetFactor()`
9849 
9850   Level: advanced
9851 
9852   Notes:
9853   Must be called after `MatFactorSetSchurIS()`.
9854 
9855   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9856 
9857 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9858 @*/
9859 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9860 {
9861   PetscFunctionBegin;
9862   PetscValidType(F, 1);
9863   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9864   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9865   PetscCall(MatFactorFactorizeSchurComplement(F));
9866   PetscCall(MatFactorInvertSchurComplement_Private(F));
9867   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9868   PetscFunctionReturn(PETSC_SUCCESS);
9869 }
9870 
9871 /*@
9872   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9873 
9874   Logically Collective
9875 
9876   Input Parameter:
9877 . F - the factored matrix obtained by calling `MatGetFactor()`
9878 
9879   Level: advanced
9880 
9881   Note:
9882   Must be called after `MatFactorSetSchurIS()`
9883 
9884 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9885 @*/
9886 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9887 {
9888   MatFactorInfo info;
9889 
9890   PetscFunctionBegin;
9891   PetscValidType(F, 1);
9892   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9893   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9894   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9895   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9896   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9897     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9898   } else {
9899     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9900   }
9901   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9902   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9903   PetscFunctionReturn(PETSC_SUCCESS);
9904 }
9905 
9906 /*@
9907   MatPtAP - Creates the matrix product $C = P^T * A * P$
9908 
9909   Neighbor-wise Collective
9910 
9911   Input Parameters:
9912 + A     - the matrix
9913 . P     - the projection matrix
9914 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9915 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9916           if the result is a dense matrix this is irrelevant
9917 
9918   Output Parameter:
9919 . C - the product matrix
9920 
9921   Level: intermediate
9922 
9923   Notes:
9924   C will be created and must be destroyed by the user with `MatDestroy()`.
9925 
9926   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9927 
9928   Developer Note:
9929   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9930 
9931 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9932 @*/
9933 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9934 {
9935   PetscFunctionBegin;
9936   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9937   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9938 
9939   if (scall == MAT_INITIAL_MATRIX) {
9940     PetscCall(MatProductCreate(A, P, NULL, C));
9941     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9942     PetscCall(MatProductSetAlgorithm(*C, "default"));
9943     PetscCall(MatProductSetFill(*C, fill));
9944 
9945     (*C)->product->api_user = PETSC_TRUE;
9946     PetscCall(MatProductSetFromOptions(*C));
9947     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);
9948     PetscCall(MatProductSymbolic(*C));
9949   } else { /* scall == MAT_REUSE_MATRIX */
9950     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9951   }
9952 
9953   PetscCall(MatProductNumeric(*C));
9954   (*C)->symmetric = A->symmetric;
9955   (*C)->spd       = A->spd;
9956   PetscFunctionReturn(PETSC_SUCCESS);
9957 }
9958 
9959 /*@
9960   MatRARt - Creates the matrix product $C = R * A * R^T$
9961 
9962   Neighbor-wise Collective
9963 
9964   Input Parameters:
9965 + A     - the matrix
9966 . R     - the projection matrix
9967 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9968 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9969           if the result is a dense matrix this is irrelevant
9970 
9971   Output Parameter:
9972 . C - the product matrix
9973 
9974   Level: intermediate
9975 
9976   Notes:
9977   C will be created and must be destroyed by the user with `MatDestroy()`.
9978 
9979   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9980 
9981   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9982   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9983   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9984   We recommend using MatPtAP().
9985 
9986 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9987 @*/
9988 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9989 {
9990   PetscFunctionBegin;
9991   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9992   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9993 
9994   if (scall == MAT_INITIAL_MATRIX) {
9995     PetscCall(MatProductCreate(A, R, NULL, C));
9996     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9997     PetscCall(MatProductSetAlgorithm(*C, "default"));
9998     PetscCall(MatProductSetFill(*C, fill));
9999 
10000     (*C)->product->api_user = PETSC_TRUE;
10001     PetscCall(MatProductSetFromOptions(*C));
10002     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);
10003     PetscCall(MatProductSymbolic(*C));
10004   } else { /* scall == MAT_REUSE_MATRIX */
10005     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10006   }
10007 
10008   PetscCall(MatProductNumeric(*C));
10009   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10010   PetscFunctionReturn(PETSC_SUCCESS);
10011 }
10012 
10013 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10014 {
10015   PetscFunctionBegin;
10016   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10017 
10018   if (scall == MAT_INITIAL_MATRIX) {
10019     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10020     PetscCall(MatProductCreate(A, B, NULL, C));
10021     PetscCall(MatProductSetType(*C, ptype));
10022     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10023     PetscCall(MatProductSetFill(*C, fill));
10024 
10025     (*C)->product->api_user = PETSC_TRUE;
10026     PetscCall(MatProductSetFromOptions(*C));
10027     PetscCall(MatProductSymbolic(*C));
10028   } else { /* scall == MAT_REUSE_MATRIX */
10029     Mat_Product *product = (*C)->product;
10030     PetscBool    isdense;
10031 
10032     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10033     if (isdense && product && product->type != ptype) {
10034       PetscCall(MatProductClear(*C));
10035       product = NULL;
10036     }
10037     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10038     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10039       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10040       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10041       product           = (*C)->product;
10042       product->fill     = fill;
10043       product->api_user = PETSC_TRUE;
10044       product->clear    = PETSC_TRUE;
10045 
10046       PetscCall(MatProductSetType(*C, ptype));
10047       PetscCall(MatProductSetFromOptions(*C));
10048       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);
10049       PetscCall(MatProductSymbolic(*C));
10050     } else { /* user may change input matrices A or B when REUSE */
10051       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10052     }
10053   }
10054   PetscCall(MatProductNumeric(*C));
10055   PetscFunctionReturn(PETSC_SUCCESS);
10056 }
10057 
10058 /*@
10059   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10060 
10061   Neighbor-wise Collective
10062 
10063   Input Parameters:
10064 + A     - the left matrix
10065 . B     - the right matrix
10066 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10067 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10068           if the result is a dense matrix this is irrelevant
10069 
10070   Output Parameter:
10071 . C - the product matrix
10072 
10073   Notes:
10074   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10075 
10076   `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
10077   call to this function with `MAT_INITIAL_MATRIX`.
10078 
10079   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10080 
10081   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`,
10082   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10083 
10084   Example of Usage:
10085 .vb
10086      MatProductCreate(A,B,NULL,&C);
10087      MatProductSetType(C,MATPRODUCT_AB);
10088      MatProductSymbolic(C);
10089      MatProductNumeric(C); // compute C=A * B
10090      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10091      MatProductNumeric(C);
10092      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10093      MatProductNumeric(C);
10094 .ve
10095 
10096   Level: intermediate
10097 
10098 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10099 @*/
10100 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10101 {
10102   PetscFunctionBegin;
10103   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10104   PetscFunctionReturn(PETSC_SUCCESS);
10105 }
10106 
10107 /*@
10108   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10109 
10110   Neighbor-wise Collective
10111 
10112   Input Parameters:
10113 + A     - the left matrix
10114 . B     - the right matrix
10115 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10116 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10117 
10118   Output Parameter:
10119 . C - the product matrix
10120 
10121   Options Database Key:
10122 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10123               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10124               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10125 
10126   Level: intermediate
10127 
10128   Notes:
10129   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10130 
10131   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10132 
10133   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10134   actually needed.
10135 
10136   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10137   and for pairs of `MATMPIDENSE` matrices.
10138 
10139   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10140 
10141 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10142 @*/
10143 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10144 {
10145   PetscFunctionBegin;
10146   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10147   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10148   PetscFunctionReturn(PETSC_SUCCESS);
10149 }
10150 
10151 /*@
10152   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10153 
10154   Neighbor-wise Collective
10155 
10156   Input Parameters:
10157 + A     - the left matrix
10158 . B     - the right matrix
10159 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10160 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10161 
10162   Output Parameter:
10163 . C - the product matrix
10164 
10165   Level: intermediate
10166 
10167   Notes:
10168   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10169 
10170   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10171 
10172   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10173 
10174   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10175   actually needed.
10176 
10177   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10178   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10179 
10180 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10181 @*/
10182 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10183 {
10184   PetscFunctionBegin;
10185   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10186   PetscFunctionReturn(PETSC_SUCCESS);
10187 }
10188 
10189 /*@
10190   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10191 
10192   Neighbor-wise Collective
10193 
10194   Input Parameters:
10195 + A     - the left matrix
10196 . B     - the middle matrix
10197 . C     - the right matrix
10198 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10199 - 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
10200           if the result is a dense matrix this is irrelevant
10201 
10202   Output Parameter:
10203 . D - the product matrix
10204 
10205   Level: intermediate
10206 
10207   Notes:
10208   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10209 
10210   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10211 
10212   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10213 
10214   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10215   actually needed.
10216 
10217   If you have many matrices with the same non-zero structure to multiply, you
10218   should use `MAT_REUSE_MATRIX` in all calls but the first
10219 
10220 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10221 @*/
10222 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10223 {
10224   PetscFunctionBegin;
10225   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10226   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10227 
10228   if (scall == MAT_INITIAL_MATRIX) {
10229     PetscCall(MatProductCreate(A, B, C, D));
10230     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10231     PetscCall(MatProductSetAlgorithm(*D, "default"));
10232     PetscCall(MatProductSetFill(*D, fill));
10233 
10234     (*D)->product->api_user = PETSC_TRUE;
10235     PetscCall(MatProductSetFromOptions(*D));
10236     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,
10237                ((PetscObject)C)->type_name);
10238     PetscCall(MatProductSymbolic(*D));
10239   } else { /* user may change input matrices when REUSE */
10240     PetscCall(MatProductReplaceMats(A, B, C, *D));
10241   }
10242   PetscCall(MatProductNumeric(*D));
10243   PetscFunctionReturn(PETSC_SUCCESS);
10244 }
10245 
10246 /*@
10247   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10248 
10249   Collective
10250 
10251   Input Parameters:
10252 + mat      - the matrix
10253 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10254 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10255 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10256 
10257   Output Parameter:
10258 . matredundant - redundant matrix
10259 
10260   Level: advanced
10261 
10262   Notes:
10263   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10264   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10265 
10266   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10267   calling it.
10268 
10269   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10270 
10271 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10272 @*/
10273 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10274 {
10275   MPI_Comm       comm;
10276   PetscMPIInt    size;
10277   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10278   Mat_Redundant *redund     = NULL;
10279   PetscSubcomm   psubcomm   = NULL;
10280   MPI_Comm       subcomm_in = subcomm;
10281   Mat           *matseq;
10282   IS             isrow, iscol;
10283   PetscBool      newsubcomm = PETSC_FALSE;
10284 
10285   PetscFunctionBegin;
10286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10287   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10288     PetscAssertPointer(*matredundant, 5);
10289     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10290   }
10291 
10292   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10293   if (size == 1 || nsubcomm == 1) {
10294     if (reuse == MAT_INITIAL_MATRIX) {
10295       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10296     } else {
10297       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");
10298       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10299     }
10300     PetscFunctionReturn(PETSC_SUCCESS);
10301   }
10302 
10303   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10304   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10305   MatCheckPreallocated(mat, 1);
10306 
10307   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10308   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10309     /* create psubcomm, then get subcomm */
10310     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10311     PetscCallMPI(MPI_Comm_size(comm, &size));
10312     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10313 
10314     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10315     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10316     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10317     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10318     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10319     newsubcomm = PETSC_TRUE;
10320     PetscCall(PetscSubcommDestroy(&psubcomm));
10321   }
10322 
10323   /* get isrow, iscol and a local sequential matrix matseq[0] */
10324   if (reuse == MAT_INITIAL_MATRIX) {
10325     mloc_sub = PETSC_DECIDE;
10326     nloc_sub = PETSC_DECIDE;
10327     if (bs < 1) {
10328       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10329       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10330     } else {
10331       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10332       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10333     }
10334     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10335     rstart = rend - mloc_sub;
10336     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10337     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10338     PetscCall(ISSetIdentity(iscol));
10339   } else { /* reuse == MAT_REUSE_MATRIX */
10340     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");
10341     /* retrieve subcomm */
10342     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10343     redund = (*matredundant)->redundant;
10344     isrow  = redund->isrow;
10345     iscol  = redund->iscol;
10346     matseq = redund->matseq;
10347   }
10348   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10349 
10350   /* get matredundant over subcomm */
10351   if (reuse == MAT_INITIAL_MATRIX) {
10352     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10353 
10354     /* create a supporting struct and attach it to C for reuse */
10355     PetscCall(PetscNew(&redund));
10356     (*matredundant)->redundant = redund;
10357     redund->isrow              = isrow;
10358     redund->iscol              = iscol;
10359     redund->matseq             = matseq;
10360     if (newsubcomm) {
10361       redund->subcomm = subcomm;
10362     } else {
10363       redund->subcomm = MPI_COMM_NULL;
10364     }
10365   } else {
10366     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10367   }
10368 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10369   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10370     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10371     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10372   }
10373 #endif
10374   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10375   PetscFunctionReturn(PETSC_SUCCESS);
10376 }
10377 
10378 /*@C
10379   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10380   a given `Mat`. Each submatrix can span multiple procs.
10381 
10382   Collective
10383 
10384   Input Parameters:
10385 + mat     - the matrix
10386 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10387 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10388 
10389   Output Parameter:
10390 . subMat - parallel sub-matrices each spanning a given `subcomm`
10391 
10392   Level: advanced
10393 
10394   Notes:
10395   The submatrix partition across processors is dictated by `subComm` a
10396   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10397   is not restricted to be grouped with consecutive original MPI processes.
10398 
10399   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10400   map directly to the layout of the original matrix [wrt the local
10401   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10402   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10403   the `subMat`. However the offDiagMat looses some columns - and this is
10404   reconstructed with `MatSetValues()`
10405 
10406   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10407 
10408 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10409 @*/
10410 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10411 {
10412   PetscMPIInt commsize, subCommSize;
10413 
10414   PetscFunctionBegin;
10415   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10416   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10417   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10418 
10419   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");
10420   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10421   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10422   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10423   PetscFunctionReturn(PETSC_SUCCESS);
10424 }
10425 
10426 /*@
10427   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10428 
10429   Not Collective
10430 
10431   Input Parameters:
10432 + mat   - matrix to extract local submatrix from
10433 . isrow - local row indices for submatrix
10434 - iscol - local column indices for submatrix
10435 
10436   Output Parameter:
10437 . submat - the submatrix
10438 
10439   Level: intermediate
10440 
10441   Notes:
10442   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10443 
10444   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10445   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10446 
10447   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10448   `MatSetValuesBlockedLocal()` will also be implemented.
10449 
10450   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10451   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10452 
10453 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10454 @*/
10455 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10456 {
10457   PetscFunctionBegin;
10458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10459   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10460   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10461   PetscCheckSameComm(isrow, 2, iscol, 3);
10462   PetscAssertPointer(submat, 4);
10463   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10464 
10465   if (mat->ops->getlocalsubmatrix) {
10466     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10467   } else {
10468     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10469   }
10470   PetscFunctionReturn(PETSC_SUCCESS);
10471 }
10472 
10473 /*@
10474   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10475 
10476   Not Collective
10477 
10478   Input Parameters:
10479 + mat    - matrix to extract local submatrix from
10480 . isrow  - local row indices for submatrix
10481 . iscol  - local column indices for submatrix
10482 - submat - the submatrix
10483 
10484   Level: intermediate
10485 
10486 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10487 @*/
10488 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10489 {
10490   PetscFunctionBegin;
10491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10492   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10493   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10494   PetscCheckSameComm(isrow, 2, iscol, 3);
10495   PetscAssertPointer(submat, 4);
10496   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10497 
10498   if (mat->ops->restorelocalsubmatrix) {
10499     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10500   } else {
10501     PetscCall(MatDestroy(submat));
10502   }
10503   *submat = NULL;
10504   PetscFunctionReturn(PETSC_SUCCESS);
10505 }
10506 
10507 /*@
10508   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10509 
10510   Collective
10511 
10512   Input Parameter:
10513 . mat - the matrix
10514 
10515   Output Parameter:
10516 . is - if any rows have zero diagonals this contains the list of them
10517 
10518   Level: developer
10519 
10520 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10521 @*/
10522 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10523 {
10524   PetscFunctionBegin;
10525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10526   PetscValidType(mat, 1);
10527   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10528   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10529 
10530   if (!mat->ops->findzerodiagonals) {
10531     Vec                diag;
10532     const PetscScalar *a;
10533     PetscInt          *rows;
10534     PetscInt           rStart, rEnd, r, nrow = 0;
10535 
10536     PetscCall(MatCreateVecs(mat, &diag, NULL));
10537     PetscCall(MatGetDiagonal(mat, diag));
10538     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10539     PetscCall(VecGetArrayRead(diag, &a));
10540     for (r = 0; r < rEnd - rStart; ++r)
10541       if (a[r] == 0.0) ++nrow;
10542     PetscCall(PetscMalloc1(nrow, &rows));
10543     nrow = 0;
10544     for (r = 0; r < rEnd - rStart; ++r)
10545       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10546     PetscCall(VecRestoreArrayRead(diag, &a));
10547     PetscCall(VecDestroy(&diag));
10548     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10549   } else {
10550     PetscUseTypeMethod(mat, findzerodiagonals, is);
10551   }
10552   PetscFunctionReturn(PETSC_SUCCESS);
10553 }
10554 
10555 /*@
10556   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10557 
10558   Collective
10559 
10560   Input Parameter:
10561 . mat - the matrix
10562 
10563   Output Parameter:
10564 . is - contains the list of rows with off block diagonal entries
10565 
10566   Level: developer
10567 
10568 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10569 @*/
10570 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10571 {
10572   PetscFunctionBegin;
10573   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10574   PetscValidType(mat, 1);
10575   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10576   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10577 
10578   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10579   PetscFunctionReturn(PETSC_SUCCESS);
10580 }
10581 
10582 /*@C
10583   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10584 
10585   Collective; No Fortran Support
10586 
10587   Input Parameter:
10588 . mat - the matrix
10589 
10590   Output Parameter:
10591 . values - the block inverses in column major order (FORTRAN-like)
10592 
10593   Level: advanced
10594 
10595   Notes:
10596   The size of the blocks is determined by the block size of the matrix.
10597 
10598   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10599 
10600   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10601 
10602 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10603 @*/
10604 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10605 {
10606   PetscFunctionBegin;
10607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10608   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10609   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10610   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10611   PetscFunctionReturn(PETSC_SUCCESS);
10612 }
10613 
10614 /*@C
10615   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10616 
10617   Collective; No Fortran Support
10618 
10619   Input Parameters:
10620 + mat     - the matrix
10621 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10622 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10623 
10624   Output Parameter:
10625 . values - the block inverses in column major order (FORTRAN-like)
10626 
10627   Level: advanced
10628 
10629   Notes:
10630   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10631 
10632   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10633 
10634 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10635 @*/
10636 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10637 {
10638   PetscFunctionBegin;
10639   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10640   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10641   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10642   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10643   PetscFunctionReturn(PETSC_SUCCESS);
10644 }
10645 
10646 /*@
10647   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10648 
10649   Collective
10650 
10651   Input Parameters:
10652 + A - the matrix
10653 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10654 
10655   Level: advanced
10656 
10657   Note:
10658   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10659 
10660 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10661 @*/
10662 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10663 {
10664   const PetscScalar *vals;
10665   PetscInt          *dnnz;
10666   PetscInt           m, rstart, rend, bs, i, j;
10667 
10668   PetscFunctionBegin;
10669   PetscCall(MatInvertBlockDiagonal(A, &vals));
10670   PetscCall(MatGetBlockSize(A, &bs));
10671   PetscCall(MatGetLocalSize(A, &m, NULL));
10672   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10673   PetscCall(PetscMalloc1(m / bs, &dnnz));
10674   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10675   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10676   PetscCall(PetscFree(dnnz));
10677   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10678   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10679   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10680   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10681   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10682   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10683   PetscFunctionReturn(PETSC_SUCCESS);
10684 }
10685 
10686 /*@C
10687   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10688   via `MatTransposeColoringCreate()`.
10689 
10690   Collective
10691 
10692   Input Parameter:
10693 . c - coloring context
10694 
10695   Level: intermediate
10696 
10697 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10698 @*/
10699 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10700 {
10701   MatTransposeColoring matcolor = *c;
10702 
10703   PetscFunctionBegin;
10704   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10705   if (--((PetscObject)matcolor)->refct > 0) {
10706     matcolor = NULL;
10707     PetscFunctionReturn(PETSC_SUCCESS);
10708   }
10709 
10710   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10711   PetscCall(PetscFree(matcolor->rows));
10712   PetscCall(PetscFree(matcolor->den2sp));
10713   PetscCall(PetscFree(matcolor->colorforcol));
10714   PetscCall(PetscFree(matcolor->columns));
10715   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10716   PetscCall(PetscHeaderDestroy(c));
10717   PetscFunctionReturn(PETSC_SUCCESS);
10718 }
10719 
10720 /*@C
10721   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10722   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10723   `MatTransposeColoring` to sparse `B`.
10724 
10725   Collective
10726 
10727   Input Parameters:
10728 + coloring - coloring context created with `MatTransposeColoringCreate()`
10729 - B        - sparse matrix
10730 
10731   Output Parameter:
10732 . Btdense - dense matrix $B^T$
10733 
10734   Level: developer
10735 
10736   Note:
10737   These are used internally for some implementations of `MatRARt()`
10738 
10739 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10740 @*/
10741 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10742 {
10743   PetscFunctionBegin;
10744   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10745   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10746   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10747 
10748   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10749   PetscFunctionReturn(PETSC_SUCCESS);
10750 }
10751 
10752 /*@C
10753   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10754   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10755   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10756   $C_{sp}$ from $C_{den}$.
10757 
10758   Collective
10759 
10760   Input Parameters:
10761 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10762 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10763 
10764   Output Parameter:
10765 . Csp - sparse matrix
10766 
10767   Level: developer
10768 
10769   Note:
10770   These are used internally for some implementations of `MatRARt()`
10771 
10772 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10773 @*/
10774 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10775 {
10776   PetscFunctionBegin;
10777   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10778   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10779   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10780 
10781   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10782   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10783   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10784   PetscFunctionReturn(PETSC_SUCCESS);
10785 }
10786 
10787 /*@C
10788   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10789 
10790   Collective
10791 
10792   Input Parameters:
10793 + mat        - the matrix product C
10794 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10795 
10796   Output Parameter:
10797 . color - the new coloring context
10798 
10799   Level: intermediate
10800 
10801 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10802           `MatTransColoringApplyDenToSp()`
10803 @*/
10804 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10805 {
10806   MatTransposeColoring c;
10807   MPI_Comm             comm;
10808 
10809   PetscFunctionBegin;
10810   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10811   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10812   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10813 
10814   c->ctype = iscoloring->ctype;
10815   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10816 
10817   *color = c;
10818   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10819   PetscFunctionReturn(PETSC_SUCCESS);
10820 }
10821 
10822 /*@
10823   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10824   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10825   same, otherwise it will be larger
10826 
10827   Not Collective
10828 
10829   Input Parameter:
10830 . mat - the matrix
10831 
10832   Output Parameter:
10833 . state - the current state
10834 
10835   Level: intermediate
10836 
10837   Notes:
10838   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10839   different matrices
10840 
10841   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10842 
10843   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10844 
10845 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10846 @*/
10847 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10848 {
10849   PetscFunctionBegin;
10850   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10851   *state = mat->nonzerostate;
10852   PetscFunctionReturn(PETSC_SUCCESS);
10853 }
10854 
10855 /*@
10856   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10857   matrices from each processor
10858 
10859   Collective
10860 
10861   Input Parameters:
10862 + comm   - the communicators the parallel matrix will live on
10863 . seqmat - the input sequential matrices
10864 . n      - number of local columns (or `PETSC_DECIDE`)
10865 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10866 
10867   Output Parameter:
10868 . mpimat - the parallel matrix generated
10869 
10870   Level: developer
10871 
10872   Note:
10873   The number of columns of the matrix in EACH processor MUST be the same.
10874 
10875 .seealso: [](ch_matrices), `Mat`
10876 @*/
10877 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10878 {
10879   PetscMPIInt size;
10880 
10881   PetscFunctionBegin;
10882   PetscCallMPI(MPI_Comm_size(comm, &size));
10883   if (size == 1) {
10884     if (reuse == MAT_INITIAL_MATRIX) {
10885       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10886     } else {
10887       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10888     }
10889     PetscFunctionReturn(PETSC_SUCCESS);
10890   }
10891 
10892   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");
10893 
10894   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10895   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10896   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10897   PetscFunctionReturn(PETSC_SUCCESS);
10898 }
10899 
10900 /*@
10901   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10902 
10903   Collective
10904 
10905   Input Parameters:
10906 + A - the matrix to create subdomains from
10907 - N - requested number of subdomains
10908 
10909   Output Parameters:
10910 + n   - number of subdomains resulting on this MPI process
10911 - iss - `IS` list with indices of subdomains on this MPI process
10912 
10913   Level: advanced
10914 
10915   Note:
10916   The number of subdomains must be smaller than the communicator size
10917 
10918 .seealso: [](ch_matrices), `Mat`, `IS`
10919 @*/
10920 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10921 {
10922   MPI_Comm    comm, subcomm;
10923   PetscMPIInt size, rank, color;
10924   PetscInt    rstart, rend, k;
10925 
10926   PetscFunctionBegin;
10927   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10928   PetscCallMPI(MPI_Comm_size(comm, &size));
10929   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10930   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);
10931   *n    = 1;
10932   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10933   color = rank / k;
10934   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10935   PetscCall(PetscMalloc1(1, iss));
10936   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10937   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10938   PetscCallMPI(MPI_Comm_free(&subcomm));
10939   PetscFunctionReturn(PETSC_SUCCESS);
10940 }
10941 
10942 /*@
10943   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10944 
10945   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10946   If they are not the same, uses `MatMatMatMult()`.
10947 
10948   Once the coarse grid problem is constructed, correct for interpolation operators
10949   that are not of full rank, which can legitimately happen in the case of non-nested
10950   geometric multigrid.
10951 
10952   Input Parameters:
10953 + restrct     - restriction operator
10954 . dA          - fine grid matrix
10955 . interpolate - interpolation operator
10956 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10957 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10958 
10959   Output Parameter:
10960 . A - the Galerkin coarse matrix
10961 
10962   Options Database Key:
10963 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10964 
10965   Level: developer
10966 
10967 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10968 @*/
10969 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10970 {
10971   IS  zerorows;
10972   Vec diag;
10973 
10974   PetscFunctionBegin;
10975   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10976   /* Construct the coarse grid matrix */
10977   if (interpolate == restrct) {
10978     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10979   } else {
10980     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10981   }
10982 
10983   /* If the interpolation matrix is not of full rank, A will have zero rows.
10984      This can legitimately happen in the case of non-nested geometric multigrid.
10985      In that event, we set the rows of the matrix to the rows of the identity,
10986      ignoring the equations (as the RHS will also be zero). */
10987 
10988   PetscCall(MatFindZeroRows(*A, &zerorows));
10989 
10990   if (zerorows != NULL) { /* if there are any zero rows */
10991     PetscCall(MatCreateVecs(*A, &diag, NULL));
10992     PetscCall(MatGetDiagonal(*A, diag));
10993     PetscCall(VecISSet(diag, zerorows, 1.0));
10994     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10995     PetscCall(VecDestroy(&diag));
10996     PetscCall(ISDestroy(&zerorows));
10997   }
10998   PetscFunctionReturn(PETSC_SUCCESS);
10999 }
11000 
11001 /*@C
11002   MatSetOperation - Allows user to set a matrix operation for any matrix type
11003 
11004   Logically Collective
11005 
11006   Input Parameters:
11007 + mat - the matrix
11008 . op  - the name of the operation
11009 - f   - the function that provides the operation
11010 
11011   Level: developer
11012 
11013   Example Usage:
11014 .vb
11015   extern PetscErrorCode usermult(Mat, Vec, Vec);
11016 
11017   PetscCall(MatCreateXXX(comm, ..., &A));
11018   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11019 .ve
11020 
11021   Notes:
11022   See the file `include/petscmat.h` for a complete list of matrix
11023   operations, which all have the form MATOP_<OPERATION>, where
11024   <OPERATION> is the name (in all capital letters) of the
11025   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11026 
11027   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11028   sequence as the usual matrix interface routines, since they
11029   are intended to be accessed via the usual matrix interface
11030   routines, e.g.,
11031 .vb
11032   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11033 .ve
11034 
11035   In particular each function MUST return `PETSC_SUCCESS` on success and
11036   nonzero on failure.
11037 
11038   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11039 
11040 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11041 @*/
11042 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11043 {
11044   PetscFunctionBegin;
11045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11046   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11047   (((void (**)(void))mat->ops)[op]) = f;
11048   PetscFunctionReturn(PETSC_SUCCESS);
11049 }
11050 
11051 /*@C
11052   MatGetOperation - Gets a matrix operation for any matrix type.
11053 
11054   Not Collective
11055 
11056   Input Parameters:
11057 + mat - the matrix
11058 - op  - the name of the operation
11059 
11060   Output Parameter:
11061 . f - the function that provides the operation
11062 
11063   Level: developer
11064 
11065   Example Usage:
11066 .vb
11067   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11068 
11069   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11070 .ve
11071 
11072   Notes:
11073   See the file include/petscmat.h for a complete list of matrix
11074   operations, which all have the form MATOP_<OPERATION>, where
11075   <OPERATION> is the name (in all capital letters) of the
11076   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11077 
11078   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11079 
11080 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11081 @*/
11082 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11083 {
11084   PetscFunctionBegin;
11085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11086   *f = (((void (**)(void))mat->ops)[op]);
11087   PetscFunctionReturn(PETSC_SUCCESS);
11088 }
11089 
11090 /*@
11091   MatHasOperation - Determines whether the given matrix supports the particular operation.
11092 
11093   Not Collective
11094 
11095   Input Parameters:
11096 + mat - the matrix
11097 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11098 
11099   Output Parameter:
11100 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11101 
11102   Level: advanced
11103 
11104   Note:
11105   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11106 
11107 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11108 @*/
11109 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11110 {
11111   PetscFunctionBegin;
11112   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11113   PetscAssertPointer(has, 3);
11114   if (mat->ops->hasoperation) {
11115     PetscUseTypeMethod(mat, hasoperation, op, has);
11116   } else {
11117     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11118     else {
11119       *has = PETSC_FALSE;
11120       if (op == MATOP_CREATE_SUBMATRIX) {
11121         PetscMPIInt size;
11122 
11123         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11124         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11125       }
11126     }
11127   }
11128   PetscFunctionReturn(PETSC_SUCCESS);
11129 }
11130 
11131 /*@
11132   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11133 
11134   Collective
11135 
11136   Input Parameter:
11137 . mat - the matrix
11138 
11139   Output Parameter:
11140 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11141 
11142   Level: beginner
11143 
11144 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11145 @*/
11146 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11147 {
11148   PetscFunctionBegin;
11149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11150   PetscValidType(mat, 1);
11151   PetscAssertPointer(cong, 2);
11152   if (!mat->rmap || !mat->cmap) {
11153     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11154     PetscFunctionReturn(PETSC_SUCCESS);
11155   }
11156   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11157     PetscCall(PetscLayoutSetUp(mat->rmap));
11158     PetscCall(PetscLayoutSetUp(mat->cmap));
11159     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11160     if (*cong) mat->congruentlayouts = 1;
11161     else mat->congruentlayouts = 0;
11162   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11163   PetscFunctionReturn(PETSC_SUCCESS);
11164 }
11165 
11166 PetscErrorCode MatSetInf(Mat A)
11167 {
11168   PetscFunctionBegin;
11169   PetscUseTypeMethod(A, setinf);
11170   PetscFunctionReturn(PETSC_SUCCESS);
11171 }
11172 
11173 /*@C
11174   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
11175   and possibly removes small values from the graph structure.
11176 
11177   Collective
11178 
11179   Input Parameters:
11180 + A       - the matrix
11181 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11182 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11183 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11184 . num_idx - size of 'index' array
11185 - index   - array of block indices to use for graph strength of connection weight
11186 
11187   Output Parameter:
11188 . graph - the resulting graph
11189 
11190   Level: advanced
11191 
11192 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11193 @*/
11194 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11195 {
11196   PetscFunctionBegin;
11197   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11198   PetscValidType(A, 1);
11199   PetscValidLogicalCollectiveBool(A, scale, 3);
11200   PetscAssertPointer(graph, 7);
11201   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11202   PetscFunctionReturn(PETSC_SUCCESS);
11203 }
11204 
11205 /*@
11206   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11207   meaning the same memory is used for the matrix, and no new memory is allocated.
11208 
11209   Collective
11210 
11211   Input Parameters:
11212 + A    - the matrix
11213 - 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
11214 
11215   Level: intermediate
11216 
11217   Developer Note:
11218   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11219   of the arrays in the data structure are unneeded.
11220 
11221 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11222 @*/
11223 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11224 {
11225   PetscFunctionBegin;
11226   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11227   PetscUseTypeMethod(A, eliminatezeros, keep);
11228   PetscFunctionReturn(PETSC_SUCCESS);
11229 }
11230