xref: /petsc/src/mat/interface/matrix.c (revision e98d5aa1d9a8b761c58f921ec2d97e44eaf55cc3)
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 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, st;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
207     PetscCall(MatGetSize(mat, &N, NULL));
208     PetscCall(MatGetLocalSize(mat, &n, NULL));
209     PetscCall(VecSet(l, 0.0));
210     PetscCall(VecSetRandom(r, NULL));
211     PetscCall(MatMult(mat, r, l));
212     PetscCall(VecGetArrayRead(l, &al));
213   } else { /* nonzero columns */
214     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
215     PetscCall(MatGetSize(mat, NULL, &N));
216     PetscCall(MatGetLocalSize(mat, NULL, &n));
217     PetscCall(VecSet(r, 0.0));
218     PetscCall(VecSetRandom(l, NULL));
219     PetscCall(MatMultTranspose(mat, l, r));
220     PetscCall(VecGetArrayRead(r, &al));
221   }
222   if (tol <= 0.0) {
223     for (i = 0, nz = 0; i < n; i++)
224       if (al[i] != 0.0) nz++;
225   } else {
226     for (i = 0, nz = 0; i < n; i++)
227       if (PetscAbsScalar(al[i]) > tol) nz++;
228   }
229   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
230   if (gnz != N) {
231     PetscInt *nzr;
232     PetscCall(PetscMalloc1(nz, &nzr));
233     if (nz) {
234       if (tol < 0) {
235         for (i = 0, nz = 0; i < n; i++)
236           if (al[i] != 0.0) nzr[nz++] = i + st;
237       } else {
238         for (i = 0, nz = 0; i < n; i++)
239           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
240       }
241     }
242     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
243   } else *nonzero = NULL;
244   if (!cols) { /* nonzero rows */
245     PetscCall(VecRestoreArrayRead(l, &al));
246   } else {
247     PetscCall(VecRestoreArrayRead(r, &al));
248   }
249   PetscCall(VecDestroy(&l));
250   PetscCall(VecDestroy(&r));
251   PetscFunctionReturn(PETSC_SUCCESS);
252 }
253 
254 /*@
255   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
256 
257   Input Parameter:
258 . mat - the matrix
259 
260   Output Parameter:
261 . keptrows - the rows that are not completely zero
262 
263   Level: intermediate
264 
265   Note:
266   `keptrows` is set to `NULL` if all rows are nonzero.
267 
268 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
269  @*/
270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
271 {
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
274   PetscValidType(mat, 1);
275   PetscAssertPointer(keptrows, 2);
276   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
277   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
278   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
279   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
280   PetscFunctionReturn(PETSC_SUCCESS);
281 }
282 
283 /*@
284   MatFindZeroRows - Locate all rows that are completely zero in the matrix
285 
286   Input Parameter:
287 . mat - the matrix
288 
289   Output Parameter:
290 . zerorows - the rows that are completely zero
291 
292   Level: intermediate
293 
294   Note:
295   `zerorows` is set to `NULL` if no rows are zero.
296 
297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
298  @*/
299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
300 {
301   IS       keptrows;
302   PetscInt m, n;
303 
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
306   PetscValidType(mat, 1);
307   PetscAssertPointer(zerorows, 2);
308   PetscCall(MatFindNonzeroRows(mat, &keptrows));
309   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
310      In keeping with this convention, we set zerorows to NULL if there are no zero
311      rows. */
312   if (keptrows == NULL) {
313     *zerorows = NULL;
314   } else {
315     PetscCall(MatGetOwnershipRange(mat, &m, &n));
316     PetscCall(ISComplement(keptrows, m, n, zerorows));
317     PetscCall(ISDestroy(&keptrows));
318   }
319   PetscFunctionReturn(PETSC_SUCCESS);
320 }
321 
322 /*@
323   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
324 
325   Not Collective
326 
327   Input Parameter:
328 . A - the matrix
329 
330   Output Parameter:
331 . a - the diagonal part (which is a SEQUENTIAL matrix)
332 
333   Level: advanced
334 
335   Notes:
336   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
337 
338   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
339 
340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
341 @*/
342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
343 {
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
346   PetscValidType(A, 1);
347   PetscAssertPointer(a, 2);
348   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
349   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
350   else {
351     PetscMPIInt size;
352 
353     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
354     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
355     *a = A;
356   }
357   PetscFunctionReturn(PETSC_SUCCESS);
358 }
359 
360 /*@
361   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
362 
363   Collective
364 
365   Input Parameter:
366 . mat - the matrix
367 
368   Output Parameter:
369 . trace - the sum of the diagonal entries
370 
371   Level: advanced
372 
373 .seealso: [](ch_matrices), `Mat`
374 @*/
375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
376 {
377   Vec diag;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
381   PetscAssertPointer(trace, 2);
382   PetscCall(MatCreateVecs(mat, &diag, NULL));
383   PetscCall(MatGetDiagonal(mat, diag));
384   PetscCall(VecSum(diag, trace));
385   PetscCall(VecDestroy(&diag));
386   PetscFunctionReturn(PETSC_SUCCESS);
387 }
388 
389 /*@
390   MatRealPart - Zeros out the imaginary part of the matrix
391 
392   Logically Collective
393 
394   Input Parameter:
395 . mat - the matrix
396 
397   Level: advanced
398 
399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
400 @*/
401 PetscErrorCode MatRealPart(Mat mat)
402 {
403   PetscFunctionBegin;
404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
405   PetscValidType(mat, 1);
406   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
407   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
408   MatCheckPreallocated(mat, 1);
409   PetscUseTypeMethod(mat, realpart);
410   PetscFunctionReturn(PETSC_SUCCESS);
411 }
412 
413 /*@C
414   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
415 
416   Collective
417 
418   Input Parameter:
419 . mat - the matrix
420 
421   Output Parameters:
422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
423 - ghosts  - the global indices of the ghost points
424 
425   Level: advanced
426 
427   Note:
428   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
429 
430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
431 @*/
432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
433 {
434   PetscFunctionBegin;
435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
436   PetscValidType(mat, 1);
437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
439   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
440   else {
441     if (nghosts) *nghosts = 0;
442     if (ghosts) *ghosts = NULL;
443   }
444   PetscFunctionReturn(PETSC_SUCCESS);
445 }
446 
447 /*@
448   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
449 
450   Logically Collective
451 
452   Input Parameter:
453 . mat - the matrix
454 
455   Level: advanced
456 
457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
458 @*/
459 PetscErrorCode MatImaginaryPart(Mat mat)
460 {
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
463   PetscValidType(mat, 1);
464   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
465   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
466   MatCheckPreallocated(mat, 1);
467   PetscUseTypeMethod(mat, imaginarypart);
468   PetscFunctionReturn(PETSC_SUCCESS);
469 }
470 
471 /*@
472   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
473 
474   Not Collective
475 
476   Input Parameter:
477 . mat - the matrix
478 
479   Output Parameters:
480 + missing - is any diagonal entry missing
481 - dd      - first diagonal entry that is missing (optional) on this process
482 
483   Level: advanced
484 
485   Note:
486   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
487 
488 .seealso: [](ch_matrices), `Mat`
489 @*/
490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
491 {
492   PetscFunctionBegin;
493   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
494   PetscValidType(mat, 1);
495   PetscAssertPointer(missing, 2);
496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
498   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
499   PetscFunctionReturn(PETSC_SUCCESS);
500 }
501 
502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
503 /*@C
504   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
505   for each row that you get to ensure that your application does
506   not bleed memory.
507 
508   Not Collective
509 
510   Input Parameters:
511 + mat - the matrix
512 - row - the row to get
513 
514   Output Parameters:
515 + ncols - if not `NULL`, the number of nonzeros in `row`
516 . cols  - if not `NULL`, the column numbers
517 - vals  - if not `NULL`, the numerical values
518 
519   Level: advanced
520 
521   Notes:
522   This routine is provided for people who need to have direct access
523   to the structure of a matrix.  We hope that we provide enough
524   high-level matrix routines that few users will need it.
525 
526   `MatGetRow()` always returns 0-based column indices, regardless of
527   whether the internal representation is 0-based (default) or 1-based.
528 
529   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
530   not wish to extract these quantities.
531 
532   The user can only examine the values extracted with `MatGetRow()`;
533   the values CANNOT be altered.  To change the matrix entries, one
534   must use `MatSetValues()`.
535 
536   You can only have one call to `MatGetRow()` outstanding for a particular
537   matrix at a time, per processor. `MatGetRow()` can only obtain rows
538   associated with the given processor, it cannot get rows from the
539   other processors; for that we suggest using `MatCreateSubMatrices()`, then
540   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
541   is in the global number of rows.
542 
543   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
544 
545   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
546 
547   Fortran Note:
548   The calling sequence is
549 .vb
550    MatGetRow(matrix,row,ncols,cols,values,ierr)
551          Mat     matrix (input)
552          integer row    (input)
553          integer ncols  (output)
554          integer cols(maxcols) (output)
555          double precision (or double complex) values(maxcols) output
556 .ve
557   where maxcols >= maximum nonzeros in any row of the matrix.
558 
559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
560 @*/
561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
562 {
563   PetscInt incols;
564 
565   PetscFunctionBegin;
566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
567   PetscValidType(mat, 1);
568   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
569   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
570   MatCheckPreallocated(mat, 1);
571   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);
572   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
573   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
574   if (ncols) *ncols = incols;
575   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
576   PetscFunctionReturn(PETSC_SUCCESS);
577 }
578 
579 /*@
580   MatConjugate - replaces the matrix values with their complex conjugates
581 
582   Logically Collective
583 
584   Input Parameter:
585 . mat - the matrix
586 
587   Level: advanced
588 
589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
590 @*/
591 PetscErrorCode MatConjugate(Mat mat)
592 {
593   PetscFunctionBegin;
594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
596   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
597     PetscUseTypeMethod(mat, conjugate);
598     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
599   }
600   PetscFunctionReturn(PETSC_SUCCESS);
601 }
602 
603 /*@C
604   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
605 
606   Not Collective
607 
608   Input Parameters:
609 + mat   - the matrix
610 . row   - the row to get
611 . ncols - the number of nonzeros
612 . cols  - the columns of the nonzeros
613 - vals  - if nonzero the column values
614 
615   Level: advanced
616 
617   Notes:
618   This routine should be called after you have finished examining the entries.
619 
620   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
621   us of the array after it has been restored. If you pass `NULL`, it will
622   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
623 
624   Fortran Notes:
625   The calling sequence is
626 .vb
627    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
628       Mat     matrix (input)
629       integer row    (input)
630       integer ncols  (output)
631       integer cols(maxcols) (output)
632       double precision (or double complex) values(maxcols) output
633 .ve
634   Where maxcols >= maximum nonzeros in any row of the matrix.
635 
636   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
637   before another call to `MatGetRow()` can be made.
638 
639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
640 @*/
641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
642 {
643   PetscFunctionBegin;
644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
645   if (ncols) PetscAssertPointer(ncols, 3);
646   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
647   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
648   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
649   if (ncols) *ncols = 0;
650   if (cols) *cols = NULL;
651   if (vals) *vals = NULL;
652   PetscFunctionReturn(PETSC_SUCCESS);
653 }
654 
655 /*@
656   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
657   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
658 
659   Not Collective
660 
661   Input Parameter:
662 . mat - the matrix
663 
664   Level: advanced
665 
666   Note:
667   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.
668 
669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
670 @*/
671 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
672 {
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
675   PetscValidType(mat, 1);
676   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
677   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
678   MatCheckPreallocated(mat, 1);
679   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
680   PetscUseTypeMethod(mat, getrowuppertriangular);
681   PetscFunctionReturn(PETSC_SUCCESS);
682 }
683 
684 /*@
685   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
686 
687   Not Collective
688 
689   Input Parameter:
690 . mat - the matrix
691 
692   Level: advanced
693 
694   Note:
695   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
696 
697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
698 @*/
699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
700 {
701   PetscFunctionBegin;
702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
703   PetscValidType(mat, 1);
704   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
705   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
706   MatCheckPreallocated(mat, 1);
707   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
708   PetscUseTypeMethod(mat, restorerowuppertriangular);
709   PetscFunctionReturn(PETSC_SUCCESS);
710 }
711 
712 /*@C
713   MatSetOptionsPrefix - Sets the prefix used for searching for all
714   `Mat` options in the database.
715 
716   Logically Collective
717 
718   Input Parameters:
719 + A      - the matrix
720 - prefix - the prefix to prepend to all option names
721 
722   Level: advanced
723 
724   Notes:
725   A hyphen (-) must NOT be given at the beginning of the prefix name.
726   The first character of all runtime options is AUTOMATICALLY the hyphen.
727 
728   This is NOT used for options for the factorization of the matrix. Normally the
729   prefix is automatically passed in from the PC calling the factorization. To set
730   it directly use  `MatSetOptionsPrefixFactor()`
731 
732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
733 @*/
734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
735 {
736   PetscFunctionBegin;
737   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
738   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
739   PetscFunctionReturn(PETSC_SUCCESS);
740 }
741 
742 /*@C
743   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
744   for matrices created with `MatGetFactor()`
745 
746   Logically Collective
747 
748   Input Parameters:
749 + A      - the matrix
750 - prefix - the prefix to prepend to all option names for the factored matrix
751 
752   Level: developer
753 
754   Notes:
755   A hyphen (-) must NOT be given at the beginning of the prefix name.
756   The first character of all runtime options is AUTOMATICALLY the hyphen.
757 
758   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
759   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
760 
761 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
762 @*/
763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
764 {
765   PetscFunctionBegin;
766   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
767   if (prefix) {
768     PetscAssertPointer(prefix, 2);
769     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
770     if (prefix != A->factorprefix) {
771       PetscCall(PetscFree(A->factorprefix));
772       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
773     }
774   } else PetscCall(PetscFree(A->factorprefix));
775   PetscFunctionReturn(PETSC_SUCCESS);
776 }
777 
778 /*@C
779   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
780   for matrices created with `MatGetFactor()`
781 
782   Logically Collective
783 
784   Input Parameters:
785 + A      - the matrix
786 - prefix - the prefix to prepend to all option names for the factored matrix
787 
788   Level: developer
789 
790   Notes:
791   A hyphen (-) must NOT be given at the beginning of the prefix name.
792   The first character of all runtime options is AUTOMATICALLY the hyphen.
793 
794   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
795   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
796 
797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
798           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
799           `MatSetOptionsPrefix()`
800 @*/
801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
802 {
803   size_t len1, len2, new_len;
804 
805   PetscFunctionBegin;
806   PetscValidHeader(A, 1);
807   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
808   if (!A->factorprefix) {
809     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
810     PetscFunctionReturn(PETSC_SUCCESS);
811   }
812   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
813 
814   PetscCall(PetscStrlen(A->factorprefix, &len1));
815   PetscCall(PetscStrlen(prefix, &len2));
816   new_len = len1 + len2 + 1;
817   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
818   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
819   PetscFunctionReturn(PETSC_SUCCESS);
820 }
821 
822 /*@C
823   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
824   matrix options in the database.
825 
826   Logically Collective
827 
828   Input Parameters:
829 + A      - the matrix
830 - prefix - the prefix to prepend to all option names
831 
832   Level: advanced
833 
834   Note:
835   A hyphen (-) must NOT be given at the beginning of the prefix name.
836   The first character of all runtime options is AUTOMATICALLY the hyphen.
837 
838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
839 @*/
840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
841 {
842   PetscFunctionBegin;
843   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
844   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
845   PetscFunctionReturn(PETSC_SUCCESS);
846 }
847 
848 /*@C
849   MatGetOptionsPrefix - Gets the prefix used for searching for all
850   matrix options in the database.
851 
852   Not Collective
853 
854   Input Parameter:
855 . A - the matrix
856 
857   Output Parameter:
858 . prefix - pointer to the prefix string used
859 
860   Level: advanced
861 
862   Fortran Note:
863   The user should pass in a string `prefix` of
864   sufficient length to hold the prefix.
865 
866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
867 @*/
868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
869 {
870   PetscFunctionBegin;
871   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
872   PetscAssertPointer(prefix, 2);
873   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
874   PetscFunctionReturn(PETSC_SUCCESS);
875 }
876 
877 /*@
878   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
879 
880   Collective
881 
882   Input Parameter:
883 . A - the matrix
884 
885   Level: beginner
886 
887   Notes:
888   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
889 
890   Users can reset the preallocation to access the original memory.
891 
892   Currently only supported for  `MATAIJ` matrices.
893 
894 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
895 @*/
896 PetscErrorCode MatResetPreallocation(Mat A)
897 {
898   PetscFunctionBegin;
899   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
900   PetscValidType(A, 1);
901   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()");
902   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
903   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
904   PetscFunctionReturn(PETSC_SUCCESS);
905 }
906 
907 /*@
908   MatSetUp - Sets up the internal matrix data structures for later use.
909 
910   Collective
911 
912   Input Parameter:
913 . A - the matrix
914 
915   Level: intermediate
916 
917   Notes:
918   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
919   setting values in the matrix.
920 
921   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
922 
923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
924 @*/
925 PetscErrorCode MatSetUp(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   if (!((PetscObject)A)->type_name) {
930     PetscMPIInt size;
931 
932     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
933     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
934   }
935   if (!A->preallocated) PetscTryTypeMethod(A, setup);
936   PetscCall(PetscLayoutSetUp(A->rmap));
937   PetscCall(PetscLayoutSetUp(A->cmap));
938   A->preallocated = PETSC_TRUE;
939   PetscFunctionReturn(PETSC_SUCCESS);
940 }
941 
942 #if defined(PETSC_HAVE_SAWS)
943   #include <petscviewersaws.h>
944 #endif
945 
946 /*
947    If threadsafety is on extraneous matrices may be printed
948 
949    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
950 */
951 #if !defined(PETSC_HAVE_THREADSAFETY)
952 static PetscInt insidematview = 0;
953 #endif
954 
955 /*@C
956   MatViewFromOptions - View properties of the matrix based on options set in the options database
957 
958   Collective
959 
960   Input Parameters:
961 + A    - the matrix
962 . obj  - optional additional object that provides the options prefix to use
963 - name - command line option
964 
965   Options Database Key:
966 . -mat_view [viewertype]:... - the viewer and its options
967 
968   Level: intermediate
969 
970   Note:
971 .vb
972     If no value is provided ascii:stdout is used
973        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
974                                                   for example ascii::ascii_info prints just the information about the object not all details
975                                                   unless :append is given filename opens in write mode, overwriting what was already there
976        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
977        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
978        socket[:port]                             defaults to the standard output port
979        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
980 .ve
981 
982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
983 @*/
984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
985 {
986   PetscFunctionBegin;
987   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
988 #if !defined(PETSC_HAVE_THREADSAFETY)
989   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
990 #endif
991   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
992   PetscFunctionReturn(PETSC_SUCCESS);
993 }
994 
995 /*@C
996   MatView - display information about a matrix in a variety ways
997 
998   Collective
999 
1000   Input Parameters:
1001 + mat    - the matrix
1002 - viewer - visualization context
1003 
1004   Options Database Keys:
1005 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1006 . -mat_view ::ascii_info_detail    - Prints more detailed info
1007 . -mat_view                        - Prints matrix in ASCII format
1008 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1009 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1010 . -display <name>                  - Sets display name (default is host)
1011 . -draw_pause <sec>                - Sets number of seconds to pause after display
1012 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1013 . -viewer_socket_machine <machine> - -
1014 . -viewer_socket_port <port>       - -
1015 . -mat_view binary                 - save matrix to file in binary format
1016 - -viewer_binary_filename <name>   - -
1017 
1018   Level: beginner
1019 
1020   Notes:
1021   The available visualization contexts include
1022 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1023 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1024 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1025 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1026 
1027   The user can open alternative visualization contexts with
1028 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1029 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1030   specified file; corresponding input uses `MatLoad()`
1031 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1032   an X window display
1033 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1034   Currently only the `MATSEQDENSE` and `MATAIJ`
1035   matrix types support the Socket viewer.
1036 
1037   The user can call `PetscViewerPushFormat()` to specify the output
1038   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1039   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1040 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1041 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1042 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1043 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1044   format common among all matrix types
1045 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1046   format (which is in many cases the same as the default)
1047 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1048   size and structure (not the matrix entries)
1049 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1050   the matrix structure
1051 
1052   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1053   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1054 
1055   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1056 
1057   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1058   viewer is used.
1059 
1060   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1061   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1062 
1063   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1064   and then use the following mouse functions.
1065 .vb
1066   left mouse: zoom in
1067   middle mouse: zoom out
1068   right mouse: continue with the simulation
1069 .ve
1070 
1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1072           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1073 @*/
1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1075 {
1076   PetscInt          rows, cols, rbs, cbs;
1077   PetscBool         isascii, isstring, issaws;
1078   PetscViewerFormat format;
1079   PetscMPIInt       size;
1080 
1081   PetscFunctionBegin;
1082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1083   PetscValidType(mat, 1);
1084   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1085   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1086   PetscCheckSameComm(mat, 1, viewer, 2);
1087 
1088   PetscCall(PetscViewerGetFormat(viewer, &format));
1089   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1090   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1091 
1092 #if !defined(PETSC_HAVE_THREADSAFETY)
1093   insidematview++;
1094 #endif
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1097   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1098   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1099 
1100   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1101   if (isascii) {
1102     if (!mat->preallocated) {
1103       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1104 #if !defined(PETSC_HAVE_THREADSAFETY)
1105       insidematview--;
1106 #endif
1107       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1108       PetscFunctionReturn(PETSC_SUCCESS);
1109     }
1110     if (!mat->assembled) {
1111       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1112 #if !defined(PETSC_HAVE_THREADSAFETY)
1113       insidematview--;
1114 #endif
1115       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1116       PetscFunctionReturn(PETSC_SUCCESS);
1117     }
1118     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1119     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1120       MatNullSpace nullsp, transnullsp;
1121 
1122       PetscCall(PetscViewerASCIIPushTab(viewer));
1123       PetscCall(MatGetSize(mat, &rows, &cols));
1124       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1125       if (rbs != 1 || cbs != 1) {
1126         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1127         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1128       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1129       if (mat->factortype) {
1130         MatSolverType solver;
1131         PetscCall(MatFactorGetSolverType(mat, &solver));
1132         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1133       }
1134       if (mat->ops->getinfo) {
1135         MatInfo info;
1136         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1137         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1138         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1139       }
1140       PetscCall(MatGetNullSpace(mat, &nullsp));
1141       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1142       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1143       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1144       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1145       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1146       PetscCall(PetscViewerASCIIPushTab(viewer));
1147       PetscCall(MatProductView(mat, viewer));
1148       PetscCall(PetscViewerASCIIPopTab(viewer));
1149     }
1150   } else if (issaws) {
1151 #if defined(PETSC_HAVE_SAWS)
1152     PetscMPIInt rank;
1153 
1154     PetscCall(PetscObjectName((PetscObject)mat));
1155     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1156     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1157 #endif
1158   } else if (isstring) {
1159     const char *type;
1160     PetscCall(MatGetType(mat, &type));
1161     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1162     PetscTryTypeMethod(mat, view, viewer);
1163   }
1164   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1165     PetscCall(PetscViewerASCIIPushTab(viewer));
1166     PetscUseTypeMethod(mat, viewnative, viewer);
1167     PetscCall(PetscViewerASCIIPopTab(viewer));
1168   } else if (mat->ops->view) {
1169     PetscCall(PetscViewerASCIIPushTab(viewer));
1170     PetscUseTypeMethod(mat, view, viewer);
1171     PetscCall(PetscViewerASCIIPopTab(viewer));
1172   }
1173   if (isascii) {
1174     PetscCall(PetscViewerGetFormat(viewer, &format));
1175     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1176   }
1177   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1178 #if !defined(PETSC_HAVE_THREADSAFETY)
1179   insidematview--;
1180 #endif
1181   PetscFunctionReturn(PETSC_SUCCESS);
1182 }
1183 
1184 #if defined(PETSC_USE_DEBUG)
1185   #include <../src/sys/totalview/tv_data_display.h>
1186 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1187 {
1188   TV_add_row("Local rows", "int", &mat->rmap->n);
1189   TV_add_row("Local columns", "int", &mat->cmap->n);
1190   TV_add_row("Global rows", "int", &mat->rmap->N);
1191   TV_add_row("Global columns", "int", &mat->cmap->N);
1192   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1193   return TV_format_OK;
1194 }
1195 #endif
1196 
1197 /*@C
1198   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1199   with `MatView()`.  The matrix format is determined from the options database.
1200   Generates a parallel MPI matrix if the communicator has more than one
1201   processor.  The default matrix type is `MATAIJ`.
1202 
1203   Collective
1204 
1205   Input Parameters:
1206 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1207             or some related function before a call to `MatLoad()`
1208 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1209 
1210   Options Database Key:
1211 . -matload_block_size <bs> - set block size
1212 
1213   Level: beginner
1214 
1215   Notes:
1216   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1217   `Mat` before calling this routine if you wish to set it from the options database.
1218 
1219   `MatLoad()` automatically loads into the options database any options
1220   given in the file filename.info where filename is the name of the file
1221   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1222   file will be ignored if you use the -viewer_binary_skip_info option.
1223 
1224   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1225   sets the default matrix type AIJ and sets the local and global sizes.
1226   If type and/or size is already set, then the same are used.
1227 
1228   In parallel, each processor can load a subset of rows (or the
1229   entire matrix).  This routine is especially useful when a large
1230   matrix is stored on disk and only part of it is desired on each
1231   processor.  For example, a parallel solver may access only some of
1232   the rows from each processor.  The algorithm used here reads
1233   relatively small blocks of data rather than reading the entire
1234   matrix and then subsetting it.
1235 
1236   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1237   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1238   or the sequence like
1239 .vb
1240     `PetscViewer` v;
1241     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1242     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1243     `PetscViewerSetFromOptions`(v);
1244     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1245     `PetscViewerFileSetName`(v,"datafile");
1246 .ve
1247   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1248 $ -viewer_type {binary, hdf5}
1249 
1250   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1251   and src/mat/tutorials/ex10.c with the second approach.
1252 
1253   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1254   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1255   Multiple objects, both matrices and vectors, can be stored within the same file.
1256   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1257 
1258   Most users should not need to know the details of the binary storage
1259   format, since `MatLoad()` and `MatView()` completely hide these details.
1260   But for anyone who is interested, the standard binary matrix storage
1261   format is
1262 
1263 .vb
1264     PetscInt    MAT_FILE_CLASSID
1265     PetscInt    number of rows
1266     PetscInt    number of columns
1267     PetscInt    total number of nonzeros
1268     PetscInt    *number nonzeros in each row
1269     PetscInt    *column indices of all nonzeros (starting index is zero)
1270     PetscScalar *values of all nonzeros
1271 .ve
1272   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1273   stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this
1274   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1275 
1276   PETSc automatically does the byte swapping for
1277   machines that store the bytes reversed. Thus if you write your own binary
1278   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1279   and `PetscBinaryWrite()` to see how this may be done.
1280 
1281   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1282   Each processor's chunk is loaded independently by its owning MPI process.
1283   Multiple objects, both matrices and vectors, can be stored within the same file.
1284   They are looked up by their PetscObject name.
1285 
1286   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1287   by default the same structure and naming of the AIJ arrays and column count
1288   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1289 $    save example.mat A b -v7.3
1290   can be directly read by this routine (see Reference 1 for details).
1291 
1292   Depending on your MATLAB version, this format might be a default,
1293   otherwise you can set it as default in Preferences.
1294 
1295   Unless -nocompression flag is used to save the file in MATLAB,
1296   PETSc must be configured with ZLIB package.
1297 
1298   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1299 
1300   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1301 
1302   Corresponding `MatView()` is not yet implemented.
1303 
1304   The loaded matrix is actually a transpose of the original one in MATLAB,
1305   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1306   With this format, matrix is automatically transposed by PETSc,
1307   unless the matrix is marked as SPD or symmetric
1308   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1309 
1310   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1311 
1312 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1313  @*/
1314 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1315 {
1316   PetscBool flg;
1317 
1318   PetscFunctionBegin;
1319   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1320   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1321 
1322   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1323 
1324   flg = PETSC_FALSE;
1325   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1326   if (flg) {
1327     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1328     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1329   }
1330   flg = PETSC_FALSE;
1331   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1332   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1333 
1334   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1335   PetscUseTypeMethod(mat, load, viewer);
1336   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1337   PetscFunctionReturn(PETSC_SUCCESS);
1338 }
1339 
1340 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1341 {
1342   Mat_Redundant *redund = *redundant;
1343 
1344   PetscFunctionBegin;
1345   if (redund) {
1346     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1347       PetscCall(ISDestroy(&redund->isrow));
1348       PetscCall(ISDestroy(&redund->iscol));
1349       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1350     } else {
1351       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1352       PetscCall(PetscFree(redund->sbuf_j));
1353       PetscCall(PetscFree(redund->sbuf_a));
1354       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1355         PetscCall(PetscFree(redund->rbuf_j[i]));
1356         PetscCall(PetscFree(redund->rbuf_a[i]));
1357       }
1358       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1359     }
1360 
1361     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1362     PetscCall(PetscFree(redund));
1363   }
1364   PetscFunctionReturn(PETSC_SUCCESS);
1365 }
1366 
1367 /*@C
1368   MatDestroy - Frees space taken by a matrix.
1369 
1370   Collective
1371 
1372   Input Parameter:
1373 . A - the matrix
1374 
1375   Level: beginner
1376 
1377   Developer Note:
1378   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1379   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1380   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1381   if changes are needed here.
1382 
1383 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1384 @*/
1385 PetscErrorCode MatDestroy(Mat *A)
1386 {
1387   PetscFunctionBegin;
1388   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1389   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1390   if (--((PetscObject)(*A))->refct > 0) {
1391     *A = NULL;
1392     PetscFunctionReturn(PETSC_SUCCESS);
1393   }
1394 
1395   /* if memory was published with SAWs then destroy it */
1396   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1397   PetscTryTypeMethod(*A, destroy);
1398 
1399   PetscCall(PetscFree((*A)->factorprefix));
1400   PetscCall(PetscFree((*A)->defaultvectype));
1401   PetscCall(PetscFree((*A)->defaultrandtype));
1402   PetscCall(PetscFree((*A)->bsizes));
1403   PetscCall(PetscFree((*A)->solvertype));
1404   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1405   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1406   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1407   PetscCall(MatProductClear(*A));
1408   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1409   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1410   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1411   PetscCall(MatDestroy(&(*A)->schur));
1412   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1413   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1414   PetscCall(PetscHeaderDestroy(A));
1415   PetscFunctionReturn(PETSC_SUCCESS);
1416 }
1417 
1418 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1419 /*@C
1420   MatSetValues - Inserts or adds a block of values into a matrix.
1421   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1422   MUST be called after all calls to `MatSetValues()` have been completed.
1423 
1424   Not Collective
1425 
1426   Input Parameters:
1427 + mat  - the matrix
1428 . v    - a logically two-dimensional array of values
1429 . m    - the number of rows
1430 . idxm - the global indices of the rows
1431 . n    - the number of columns
1432 . idxn - the global indices of the columns
1433 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1434 
1435   Level: beginner
1436 
1437   Notes:
1438   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1439 
1440   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1441   options cannot be mixed without intervening calls to the assembly
1442   routines.
1443 
1444   `MatSetValues()` uses 0-based row and column numbers in Fortran
1445   as well as in C.
1446 
1447   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1448   simply ignored. This allows easily inserting element stiffness matrices
1449   with homogeneous Dirichlet boundary conditions that you don't want represented
1450   in the matrix.
1451 
1452   Efficiency Alert:
1453   The routine `MatSetValuesBlocked()` may offer much better efficiency
1454   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1455 
1456   Developer Note:
1457   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1458   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1459 
1460 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1461           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1462 @*/
1463 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1464 {
1465   PetscFunctionBeginHot;
1466   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1467   PetscValidType(mat, 1);
1468   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1469   PetscAssertPointer(idxm, 3);
1470   PetscAssertPointer(idxn, 5);
1471   MatCheckPreallocated(mat, 1);
1472 
1473   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1474   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1475 
1476   if (PetscDefined(USE_DEBUG)) {
1477     PetscInt i, j;
1478 
1479     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1480     for (i = 0; i < m; i++) {
1481       for (j = 0; j < n; j++) {
1482         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1483 #if defined(PETSC_USE_COMPLEX)
1484           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]);
1485 #else
1486           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]);
1487 #endif
1488       }
1489     }
1490     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);
1491     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);
1492   }
1493 
1494   if (mat->assembled) {
1495     mat->was_assembled = PETSC_TRUE;
1496     mat->assembled     = PETSC_FALSE;
1497   }
1498   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1499   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1500   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1501   PetscFunctionReturn(PETSC_SUCCESS);
1502 }
1503 
1504 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1505 /*@C
1506   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1507   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1508   MUST be called after all calls to `MatSetValues()` have been completed.
1509 
1510   Not Collective
1511 
1512   Input Parameters:
1513 + mat  - the matrix
1514 . v    - a logically two-dimensional array of values
1515 . ism  - the rows to provide
1516 . isn  - the columns to provide
1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519   Level: beginner
1520 
1521   Notes:
1522   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1523 
1524   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525   options cannot be mixed without intervening calls to the assembly
1526   routines.
1527 
1528   `MatSetValues()` uses 0-based row and column numbers in Fortran
1529   as well as in C.
1530 
1531   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1532   simply ignored. This allows easily inserting element stiffness matrices
1533   with homogeneous Dirichlet boundary conditions that you don't want represented
1534   in the matrix.
1535 
1536   Efficiency Alert:
1537   The routine `MatSetValuesBlocked()` may offer much better efficiency
1538   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540   This is currently not optimized for any particular `ISType`
1541 
1542   Developer Note:
1543   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1544   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1545 
1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1547           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1548 @*/
1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1550 {
1551   PetscInt        m, n;
1552   const PetscInt *rows, *cols;
1553 
1554   PetscFunctionBeginHot;
1555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1556   PetscCall(ISGetIndices(ism, &rows));
1557   PetscCall(ISGetIndices(isn, &cols));
1558   PetscCall(ISGetLocalSize(ism, &m));
1559   PetscCall(ISGetLocalSize(isn, &n));
1560   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1561   PetscCall(ISRestoreIndices(ism, &rows));
1562   PetscCall(ISRestoreIndices(isn, &cols));
1563   PetscFunctionReturn(PETSC_SUCCESS);
1564 }
1565 
1566 /*@
1567   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1568   values into a matrix
1569 
1570   Not Collective
1571 
1572   Input Parameters:
1573 + mat - the matrix
1574 . row - the (block) row to set
1575 - v   - a logically two-dimensional array of values
1576 
1577   Level: intermediate
1578 
1579   Notes:
1580   The values, `v`, are column-oriented (for the block version) and sorted
1581 
1582   All the nonzero values in `row` must be provided
1583 
1584   The matrix must have previously had its column indices set, likely by having been assembled.
1585 
1586   `row` must belong to this MPI process
1587 
1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1589           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1590 @*/
1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1592 {
1593   PetscInt globalrow;
1594 
1595   PetscFunctionBegin;
1596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1597   PetscValidType(mat, 1);
1598   PetscAssertPointer(v, 3);
1599   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1600   PetscCall(MatSetValuesRow(mat, globalrow, v));
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 /*@
1605   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1606   values into a matrix
1607 
1608   Not Collective
1609 
1610   Input Parameters:
1611 + mat - the matrix
1612 . row - the (block) row to set
1613 - 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
1614 
1615   Level: advanced
1616 
1617   Notes:
1618   The values, `v`, are column-oriented for the block version.
1619 
1620   All the nonzeros in `row` must be provided
1621 
1622   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1623 
1624   `row` must belong to this process
1625 
1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1627           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1628 @*/
1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1630 {
1631   PetscFunctionBeginHot;
1632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1633   PetscValidType(mat, 1);
1634   MatCheckPreallocated(mat, 1);
1635   PetscAssertPointer(v, 3);
1636   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1637   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1638   mat->insertmode = INSERT_VALUES;
1639 
1640   if (mat->assembled) {
1641     mat->was_assembled = PETSC_TRUE;
1642     mat->assembled     = PETSC_FALSE;
1643   }
1644   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1645   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1646   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1647   PetscFunctionReturn(PETSC_SUCCESS);
1648 }
1649 
1650 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1651 /*@
1652   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1653   Using structured grid indexing
1654 
1655   Not Collective
1656 
1657   Input Parameters:
1658 + mat  - the matrix
1659 . m    - number of rows being entered
1660 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1661 . n    - number of columns being entered
1662 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1663 . v    - a logically two-dimensional array of values
1664 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1665 
1666   Level: beginner
1667 
1668   Notes:
1669   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1670 
1671   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1672   options cannot be mixed without intervening calls to the assembly
1673   routines.
1674 
1675   The grid coordinates are across the entire grid, not just the local portion
1676 
1677   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1678   as well as in C.
1679 
1680   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1681 
1682   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1683   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1684 
1685   The columns and rows in the stencil passed in MUST be contained within the
1686   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1687   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1688   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1689   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1690 
1691   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1692   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1693   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1694   `DM_BOUNDARY_PERIODIC` boundary type.
1695 
1696   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
1697   a single value per point) you can skip filling those indices.
1698 
1699   Inspired by the structured grid interface to the HYPRE package
1700   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1701 
1702   Efficiency Alert:
1703   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1704   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1705 
1706   Fortran Note:
1707   `idxm` and `idxn` should be declared as
1708 $     MatStencil idxm(4,m),idxn(4,n)
1709   and the values inserted using
1710 .vb
1711     idxm(MatStencil_i,1) = i
1712     idxm(MatStencil_j,1) = j
1713     idxm(MatStencil_k,1) = k
1714     idxm(MatStencil_c,1) = c
1715     etc
1716 .ve
1717 
1718 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1719           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1720 @*/
1721 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1722 {
1723   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1724   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1725   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1726 
1727   PetscFunctionBegin;
1728   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1730   PetscValidType(mat, 1);
1731   PetscAssertPointer(idxm, 3);
1732   PetscAssertPointer(idxn, 5);
1733 
1734   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1735     jdxm = buf;
1736     jdxn = buf + m;
1737   } else {
1738     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1739     jdxm = bufm;
1740     jdxn = bufn;
1741   }
1742   for (i = 0; i < m; i++) {
1743     for (j = 0; j < 3 - sdim; j++) dxm++;
1744     tmp = *dxm++ - starts[0];
1745     for (j = 0; j < dim - 1; j++) {
1746       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1747       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1748     }
1749     if (mat->stencil.noc) dxm++;
1750     jdxm[i] = tmp;
1751   }
1752   for (i = 0; i < n; i++) {
1753     for (j = 0; j < 3 - sdim; j++) dxn++;
1754     tmp = *dxn++ - starts[0];
1755     for (j = 0; j < dim - 1; j++) {
1756       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1757       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1758     }
1759     if (mat->stencil.noc) dxn++;
1760     jdxn[i] = tmp;
1761   }
1762   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1763   PetscCall(PetscFree2(bufm, bufn));
1764   PetscFunctionReturn(PETSC_SUCCESS);
1765 }
1766 
1767 /*@
1768   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1769   Using structured grid indexing
1770 
1771   Not Collective
1772 
1773   Input Parameters:
1774 + mat  - the matrix
1775 . m    - number of rows being entered
1776 . idxm - grid coordinates for matrix rows being entered
1777 . n    - number of columns being entered
1778 . idxn - grid coordinates for matrix columns being entered
1779 . v    - a logically two-dimensional array of values
1780 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1781 
1782   Level: beginner
1783 
1784   Notes:
1785   By default the values, `v`, are row-oriented and unsorted.
1786   See `MatSetOption()` for other options.
1787 
1788   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1789   options cannot be mixed without intervening calls to the assembly
1790   routines.
1791 
1792   The grid coordinates are across the entire grid, not just the local portion
1793 
1794   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1795   as well as in C.
1796 
1797   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1798 
1799   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1800   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1801 
1802   The columns and rows in the stencil passed in MUST be contained within the
1803   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1804   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1805   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1806   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1807 
1808   Negative indices may be passed in idxm and idxn, these rows and columns are
1809   simply ignored. This allows easily inserting element stiffness matrices
1810   with homogeneous Dirichlet boundary conditions that you don't want represented
1811   in the matrix.
1812 
1813   Inspired by the structured grid interface to the HYPRE package
1814   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1815 
1816   Fortran Note:
1817   `idxm` and `idxn` should be declared as
1818 $     MatStencil idxm(4,m),idxn(4,n)
1819   and the values inserted using
1820 .vb
1821     idxm(MatStencil_i,1) = i
1822     idxm(MatStencil_j,1) = j
1823     idxm(MatStencil_k,1) = k
1824    etc
1825 .ve
1826 
1827 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1828           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1829           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1830 @*/
1831 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1832 {
1833   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1834   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1835   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1836 
1837   PetscFunctionBegin;
1838   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1839   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1840   PetscValidType(mat, 1);
1841   PetscAssertPointer(idxm, 3);
1842   PetscAssertPointer(idxn, 5);
1843   PetscAssertPointer(v, 6);
1844 
1845   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1846     jdxm = buf;
1847     jdxn = buf + m;
1848   } else {
1849     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1850     jdxm = bufm;
1851     jdxn = bufn;
1852   }
1853   for (i = 0; i < m; i++) {
1854     for (j = 0; j < 3 - sdim; j++) dxm++;
1855     tmp = *dxm++ - starts[0];
1856     for (j = 0; j < sdim - 1; j++) {
1857       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1858       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1859     }
1860     dxm++;
1861     jdxm[i] = tmp;
1862   }
1863   for (i = 0; i < n; i++) {
1864     for (j = 0; j < 3 - sdim; j++) dxn++;
1865     tmp = *dxn++ - starts[0];
1866     for (j = 0; j < sdim - 1; j++) {
1867       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1868       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1869     }
1870     dxn++;
1871     jdxn[i] = tmp;
1872   }
1873   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1874   PetscCall(PetscFree2(bufm, bufn));
1875   PetscFunctionReturn(PETSC_SUCCESS);
1876 }
1877 
1878 /*@
1879   MatSetStencil - Sets the grid information for setting values into a matrix via
1880   `MatSetValuesStencil()`
1881 
1882   Not Collective
1883 
1884   Input Parameters:
1885 + mat    - the matrix
1886 . dim    - dimension of the grid 1, 2, or 3
1887 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1888 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1889 - dof    - number of degrees of freedom per node
1890 
1891   Level: beginner
1892 
1893   Notes:
1894   Inspired by the structured grid interface to the HYPRE package
1895   (www.llnl.gov/CASC/hyper)
1896 
1897   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1898   user.
1899 
1900 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1901           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1902 @*/
1903 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1904 {
1905   PetscFunctionBegin;
1906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1907   PetscAssertPointer(dims, 3);
1908   PetscAssertPointer(starts, 4);
1909 
1910   mat->stencil.dim = dim + (dof > 1);
1911   for (PetscInt i = 0; i < dim; i++) {
1912     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1913     mat->stencil.starts[i] = starts[dim - i - 1];
1914   }
1915   mat->stencil.dims[dim]   = dof;
1916   mat->stencil.starts[dim] = 0;
1917   mat->stencil.noc         = (PetscBool)(dof == 1);
1918   PetscFunctionReturn(PETSC_SUCCESS);
1919 }
1920 
1921 /*@C
1922   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1923 
1924   Not Collective
1925 
1926   Input Parameters:
1927 + mat  - the matrix
1928 . v    - a logically two-dimensional array of values
1929 . m    - the number of block rows
1930 . idxm - the global block indices
1931 . n    - the number of block columns
1932 . idxn - the global block indices
1933 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1934 
1935   Level: intermediate
1936 
1937   Notes:
1938   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1939   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1940 
1941   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1942   NOT the total number of rows/columns; for example, if the block size is 2 and
1943   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1944   The values in idxm would be 1 2; that is the first index for each block divided by
1945   the block size.
1946 
1947   You must call `MatSetBlockSize()` when constructing this matrix (before
1948   preallocating it).
1949 
1950   By default the values, `v`, are row-oriented, so the layout of
1951   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1952 
1953   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1954   options cannot be mixed without intervening calls to the assembly
1955   routines.
1956 
1957   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1958   as well as in C.
1959 
1960   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1961   simply ignored. This allows easily inserting element stiffness matrices
1962   with homogeneous Dirichlet boundary conditions that you don't want represented
1963   in the matrix.
1964 
1965   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1966   internal searching must be done to determine where to place the
1967   data in the matrix storage space.  By instead inserting blocks of
1968   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1969   reduced.
1970 
1971   Example:
1972 .vb
1973    Suppose m=n=2 and block size(bs) = 2 The array is
1974 
1975    1  2  | 3  4
1976    5  6  | 7  8
1977    - - - | - - -
1978    9  10 | 11 12
1979    13 14 | 15 16
1980 
1981    v[] should be passed in like
1982    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1983 
1984   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1985    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1986 .ve
1987 
1988 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1989 @*/
1990 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1991 {
1992   PetscFunctionBeginHot;
1993   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1994   PetscValidType(mat, 1);
1995   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1996   PetscAssertPointer(idxm, 3);
1997   PetscAssertPointer(idxn, 5);
1998   MatCheckPreallocated(mat, 1);
1999   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2000   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2001   if (PetscDefined(USE_DEBUG)) {
2002     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2003     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2004   }
2005   if (PetscDefined(USE_DEBUG)) {
2006     PetscInt rbs, cbs, M, N, i;
2007     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2008     PetscCall(MatGetSize(mat, &M, &N));
2009     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);
2010     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);
2011   }
2012   if (mat->assembled) {
2013     mat->was_assembled = PETSC_TRUE;
2014     mat->assembled     = PETSC_FALSE;
2015   }
2016   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2017   if (mat->ops->setvaluesblocked) {
2018     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2019   } else {
2020     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2021     PetscInt i, j, bs, cbs;
2022 
2023     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2024     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2025       iidxm = buf;
2026       iidxn = buf + m * bs;
2027     } else {
2028       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2029       iidxm = bufr;
2030       iidxn = bufc;
2031     }
2032     for (i = 0; i < m; i++) {
2033       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2034     }
2035     if (m != n || bs != cbs || idxm != idxn) {
2036       for (i = 0; i < n; i++) {
2037         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2038       }
2039     } else iidxn = iidxm;
2040     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2041     PetscCall(PetscFree2(bufr, bufc));
2042   }
2043   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2044   PetscFunctionReturn(PETSC_SUCCESS);
2045 }
2046 
2047 /*@C
2048   MatGetValues - Gets a block of local values from a matrix.
2049 
2050   Not Collective; can only return values that are owned by the give process
2051 
2052   Input Parameters:
2053 + mat  - the matrix
2054 . v    - a logically two-dimensional array for storing the values
2055 . m    - the number of rows
2056 . idxm - the  global indices of the rows
2057 . n    - the number of columns
2058 - idxn - the global indices of the columns
2059 
2060   Level: advanced
2061 
2062   Notes:
2063   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2064   The values, `v`, are then returned in a row-oriented format,
2065   analogous to that used by default in `MatSetValues()`.
2066 
2067   `MatGetValues()` uses 0-based row and column numbers in
2068   Fortran as well as in C.
2069 
2070   `MatGetValues()` requires that the matrix has been assembled
2071   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2072   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2073   without intermediate matrix assembly.
2074 
2075   Negative row or column indices will be ignored and those locations in `v` will be
2076   left unchanged.
2077 
2078   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2079   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2080   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2081 
2082 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2083 @*/
2084 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2085 {
2086   PetscFunctionBegin;
2087   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2088   PetscValidType(mat, 1);
2089   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2090   PetscAssertPointer(idxm, 3);
2091   PetscAssertPointer(idxn, 5);
2092   PetscAssertPointer(v, 6);
2093   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2094   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2095   MatCheckPreallocated(mat, 1);
2096 
2097   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2098   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2099   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2100   PetscFunctionReturn(PETSC_SUCCESS);
2101 }
2102 
2103 /*@C
2104   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2105   defined previously by `MatSetLocalToGlobalMapping()`
2106 
2107   Not Collective
2108 
2109   Input Parameters:
2110 + mat  - the matrix
2111 . nrow - number of rows
2112 . irow - the row local indices
2113 . ncol - number of columns
2114 - icol - the column local indices
2115 
2116   Output Parameter:
2117 . y - a logically two-dimensional array of values
2118 
2119   Level: advanced
2120 
2121   Notes:
2122   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2123 
2124   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,
2125   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2126   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2127   with `MatSetLocalToGlobalMapping()`.
2128 
2129   Developer Note:
2130   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2131   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2132 
2133 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2134           `MatSetValuesLocal()`, `MatGetValues()`
2135 @*/
2136 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2137 {
2138   PetscFunctionBeginHot;
2139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2140   PetscValidType(mat, 1);
2141   MatCheckPreallocated(mat, 1);
2142   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2143   PetscAssertPointer(irow, 3);
2144   PetscAssertPointer(icol, 5);
2145   if (PetscDefined(USE_DEBUG)) {
2146     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2147     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2148   }
2149   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2150   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2151   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2152   else {
2153     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2154     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2155       irowm = buf;
2156       icolm = buf + nrow;
2157     } else {
2158       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2159       irowm = bufr;
2160       icolm = bufc;
2161     }
2162     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2163     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2164     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2165     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2166     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2167     PetscCall(PetscFree2(bufr, bufc));
2168   }
2169   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2170   PetscFunctionReturn(PETSC_SUCCESS);
2171 }
2172 
2173 /*@
2174   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2175   the same size. Currently, this can only be called once and creates the given matrix.
2176 
2177   Not Collective
2178 
2179   Input Parameters:
2180 + mat  - the matrix
2181 . nb   - the number of blocks
2182 . bs   - the number of rows (and columns) in each block
2183 . rows - a concatenation of the rows for each block
2184 - v    - a concatenation of logically two-dimensional arrays of values
2185 
2186   Level: advanced
2187 
2188   Notes:
2189   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2190 
2191   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2192 
2193 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2194           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2195 @*/
2196 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2197 {
2198   PetscFunctionBegin;
2199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2200   PetscValidType(mat, 1);
2201   PetscAssertPointer(rows, 4);
2202   PetscAssertPointer(v, 5);
2203   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2204 
2205   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2206   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2207   else {
2208     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2209   }
2210   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2211   PetscFunctionReturn(PETSC_SUCCESS);
2212 }
2213 
2214 /*@
2215   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2216   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2217   using a local (per-processor) numbering.
2218 
2219   Not Collective
2220 
2221   Input Parameters:
2222 + x        - the matrix
2223 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2224 - cmapping - column mapping
2225 
2226   Level: intermediate
2227 
2228   Note:
2229   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2230 
2231 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2232 @*/
2233 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2234 {
2235   PetscFunctionBegin;
2236   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2237   PetscValidType(x, 1);
2238   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2239   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2240   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2241   else {
2242     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2243     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2244   }
2245   PetscFunctionReturn(PETSC_SUCCESS);
2246 }
2247 
2248 /*@
2249   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2250 
2251   Not Collective
2252 
2253   Input Parameter:
2254 . A - the matrix
2255 
2256   Output Parameters:
2257 + rmapping - row mapping
2258 - cmapping - column mapping
2259 
2260   Level: advanced
2261 
2262 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2263 @*/
2264 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2265 {
2266   PetscFunctionBegin;
2267   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2268   PetscValidType(A, 1);
2269   if (rmapping) {
2270     PetscAssertPointer(rmapping, 2);
2271     *rmapping = A->rmap->mapping;
2272   }
2273   if (cmapping) {
2274     PetscAssertPointer(cmapping, 3);
2275     *cmapping = A->cmap->mapping;
2276   }
2277   PetscFunctionReturn(PETSC_SUCCESS);
2278 }
2279 
2280 /*@
2281   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2282 
2283   Logically Collective
2284 
2285   Input Parameters:
2286 + A    - the matrix
2287 . rmap - row layout
2288 - cmap - column layout
2289 
2290   Level: advanced
2291 
2292   Note:
2293   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2294 
2295 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2296 @*/
2297 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2298 {
2299   PetscFunctionBegin;
2300   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2301   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2302   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2303   PetscFunctionReturn(PETSC_SUCCESS);
2304 }
2305 
2306 /*@
2307   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2308 
2309   Not Collective
2310 
2311   Input Parameter:
2312 . A - the matrix
2313 
2314   Output Parameters:
2315 + rmap - row layout
2316 - cmap - column layout
2317 
2318   Level: advanced
2319 
2320 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2321 @*/
2322 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2323 {
2324   PetscFunctionBegin;
2325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2326   PetscValidType(A, 1);
2327   if (rmap) {
2328     PetscAssertPointer(rmap, 2);
2329     *rmap = A->rmap;
2330   }
2331   if (cmap) {
2332     PetscAssertPointer(cmap, 3);
2333     *cmap = A->cmap;
2334   }
2335   PetscFunctionReturn(PETSC_SUCCESS);
2336 }
2337 
2338 /*@C
2339   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2340   using a local numbering of the rows and columns.
2341 
2342   Not Collective
2343 
2344   Input Parameters:
2345 + mat  - the matrix
2346 . nrow - number of rows
2347 . irow - the row local indices
2348 . ncol - number of columns
2349 . icol - the column local indices
2350 . y    - a logically two-dimensional array of values
2351 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2352 
2353   Level: intermediate
2354 
2355   Notes:
2356   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2357 
2358   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2359   options cannot be mixed without intervening calls to the assembly
2360   routines.
2361 
2362   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2363   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2364 
2365   Developer Note:
2366   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2367   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2368 
2369 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2370           `MatGetValuesLocal()`
2371 @*/
2372 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2373 {
2374   PetscFunctionBeginHot;
2375   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2376   PetscValidType(mat, 1);
2377   MatCheckPreallocated(mat, 1);
2378   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2379   PetscAssertPointer(irow, 3);
2380   PetscAssertPointer(icol, 5);
2381   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2382   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2383   if (PetscDefined(USE_DEBUG)) {
2384     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2385     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2386   }
2387 
2388   if (mat->assembled) {
2389     mat->was_assembled = PETSC_TRUE;
2390     mat->assembled     = PETSC_FALSE;
2391   }
2392   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2393   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2394   else {
2395     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2396     const PetscInt *irowm, *icolm;
2397 
2398     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2399       bufr  = buf;
2400       bufc  = buf + nrow;
2401       irowm = bufr;
2402       icolm = bufc;
2403     } else {
2404       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2405       irowm = bufr;
2406       icolm = bufc;
2407     }
2408     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2409     else irowm = irow;
2410     if (mat->cmap->mapping) {
2411       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2412         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2413       } else icolm = irowm;
2414     } else icolm = icol;
2415     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2416     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2417   }
2418   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2419   PetscFunctionReturn(PETSC_SUCCESS);
2420 }
2421 
2422 /*@C
2423   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2424   using a local ordering of the nodes a block at a time.
2425 
2426   Not Collective
2427 
2428   Input Parameters:
2429 + mat  - the matrix
2430 . nrow - number of rows
2431 . irow - the row local indices
2432 . ncol - number of columns
2433 . icol - the column local indices
2434 . y    - a logically two-dimensional array of values
2435 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2436 
2437   Level: intermediate
2438 
2439   Notes:
2440   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2441   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2442 
2443   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2444   options cannot be mixed without intervening calls to the assembly
2445   routines.
2446 
2447   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2448   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2449 
2450   Developer Note:
2451   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2452   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2453 
2454 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2455           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2456 @*/
2457 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2458 {
2459   PetscFunctionBeginHot;
2460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2461   PetscValidType(mat, 1);
2462   MatCheckPreallocated(mat, 1);
2463   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2464   PetscAssertPointer(irow, 3);
2465   PetscAssertPointer(icol, 5);
2466   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2467   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2468   if (PetscDefined(USE_DEBUG)) {
2469     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2470     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);
2471   }
2472 
2473   if (mat->assembled) {
2474     mat->was_assembled = PETSC_TRUE;
2475     mat->assembled     = PETSC_FALSE;
2476   }
2477   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2478     PetscInt irbs, rbs;
2479     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2480     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2481     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2482   }
2483   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2484     PetscInt icbs, cbs;
2485     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2486     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2487     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2488   }
2489   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2490   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2491   else {
2492     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2493     const PetscInt *irowm, *icolm;
2494 
2495     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2496       bufr  = buf;
2497       bufc  = buf + nrow;
2498       irowm = bufr;
2499       icolm = bufc;
2500     } else {
2501       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2502       irowm = bufr;
2503       icolm = bufc;
2504     }
2505     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2506     else irowm = irow;
2507     if (mat->cmap->mapping) {
2508       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2509         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2510       } else icolm = irowm;
2511     } else icolm = icol;
2512     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2513     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2514   }
2515   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2516   PetscFunctionReturn(PETSC_SUCCESS);
2517 }
2518 
2519 /*@
2520   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2521 
2522   Collective
2523 
2524   Input Parameters:
2525 + mat - the matrix
2526 - x   - the vector to be multiplied
2527 
2528   Output Parameter:
2529 . y - the result
2530 
2531   Level: developer
2532 
2533   Note:
2534   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2535   call `MatMultDiagonalBlock`(A,y,y).
2536 
2537 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2538 @*/
2539 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2540 {
2541   PetscFunctionBegin;
2542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2543   PetscValidType(mat, 1);
2544   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2545   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2546 
2547   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2548   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2549   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2550   MatCheckPreallocated(mat, 1);
2551 
2552   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2553   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2554   PetscFunctionReturn(PETSC_SUCCESS);
2555 }
2556 
2557 /*@
2558   MatMult - Computes the matrix-vector product, $y = Ax$.
2559 
2560   Neighbor-wise Collective
2561 
2562   Input Parameters:
2563 + mat - the matrix
2564 - x   - the vector to be multiplied
2565 
2566   Output Parameter:
2567 . y - the result
2568 
2569   Level: beginner
2570 
2571   Note:
2572   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2573   call `MatMult`(A,y,y).
2574 
2575 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2576 @*/
2577 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2578 {
2579   PetscFunctionBegin;
2580   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2581   PetscValidType(mat, 1);
2582   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2583   VecCheckAssembled(x);
2584   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2585   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2586   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2587   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2588   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);
2589   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);
2590   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);
2591   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);
2592   PetscCall(VecSetErrorIfLocked(y, 3));
2593   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2594   MatCheckPreallocated(mat, 1);
2595 
2596   PetscCall(VecLockReadPush(x));
2597   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2598   PetscUseTypeMethod(mat, mult, x, y);
2599   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2600   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2601   PetscCall(VecLockReadPop(x));
2602   PetscFunctionReturn(PETSC_SUCCESS);
2603 }
2604 
2605 /*@
2606   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2607 
2608   Neighbor-wise Collective
2609 
2610   Input Parameters:
2611 + mat - the matrix
2612 - x   - the vector to be multiplied
2613 
2614   Output Parameter:
2615 . y - the result
2616 
2617   Level: beginner
2618 
2619   Notes:
2620   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2621   call `MatMultTranspose`(A,y,y).
2622 
2623   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2624   use `MatMultHermitianTranspose()`
2625 
2626 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2627 @*/
2628 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2629 {
2630   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2631 
2632   PetscFunctionBegin;
2633   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2634   PetscValidType(mat, 1);
2635   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2636   VecCheckAssembled(x);
2637   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2638 
2639   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2640   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2641   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2642   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);
2643   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);
2644   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);
2645   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);
2646   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2647   MatCheckPreallocated(mat, 1);
2648 
2649   if (!mat->ops->multtranspose) {
2650     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2651     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);
2652   } else op = mat->ops->multtranspose;
2653   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2654   PetscCall(VecLockReadPush(x));
2655   PetscCall((*op)(mat, x, y));
2656   PetscCall(VecLockReadPop(x));
2657   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2658   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2659   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2660   PetscFunctionReturn(PETSC_SUCCESS);
2661 }
2662 
2663 /*@
2664   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2665 
2666   Neighbor-wise Collective
2667 
2668   Input Parameters:
2669 + mat - the matrix
2670 - x   - the vector to be multiplied
2671 
2672   Output Parameter:
2673 . y - the result
2674 
2675   Level: beginner
2676 
2677   Notes:
2678   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2679   call `MatMultHermitianTranspose`(A,y,y).
2680 
2681   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2682 
2683   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2684 
2685 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2686 @*/
2687 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2688 {
2689   PetscFunctionBegin;
2690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2691   PetscValidType(mat, 1);
2692   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2693   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2694 
2695   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2696   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2697   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2698   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);
2699   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);
2700   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);
2701   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);
2702   MatCheckPreallocated(mat, 1);
2703 
2704   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2705 #if defined(PETSC_USE_COMPLEX)
2706   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2707     PetscCall(VecLockReadPush(x));
2708     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2709     else PetscUseTypeMethod(mat, mult, x, y);
2710     PetscCall(VecLockReadPop(x));
2711   } else {
2712     Vec w;
2713     PetscCall(VecDuplicate(x, &w));
2714     PetscCall(VecCopy(x, w));
2715     PetscCall(VecConjugate(w));
2716     PetscCall(MatMultTranspose(mat, w, y));
2717     PetscCall(VecDestroy(&w));
2718     PetscCall(VecConjugate(y));
2719   }
2720   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2721 #else
2722   PetscCall(MatMultTranspose(mat, x, y));
2723 #endif
2724   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2725   PetscFunctionReturn(PETSC_SUCCESS);
2726 }
2727 
2728 /*@
2729   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2730 
2731   Neighbor-wise Collective
2732 
2733   Input Parameters:
2734 + mat - the matrix
2735 . v1  - the vector to be multiplied by `mat`
2736 - v2  - the vector to be added to the result
2737 
2738   Output Parameter:
2739 . v3 - the result
2740 
2741   Level: beginner
2742 
2743   Note:
2744   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2745   call `MatMultAdd`(A,v1,v2,v1).
2746 
2747 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2748 @*/
2749 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2750 {
2751   PetscFunctionBegin;
2752   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2753   PetscValidType(mat, 1);
2754   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2755   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2756   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2757 
2758   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2759   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2760   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);
2761   /* 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);
2762      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); */
2763   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);
2764   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);
2765   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2766   MatCheckPreallocated(mat, 1);
2767 
2768   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2769   PetscCall(VecLockReadPush(v1));
2770   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2771   PetscCall(VecLockReadPop(v1));
2772   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2773   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2774   PetscFunctionReturn(PETSC_SUCCESS);
2775 }
2776 
2777 /*@
2778   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2779 
2780   Neighbor-wise Collective
2781 
2782   Input Parameters:
2783 + mat - the matrix
2784 . v1  - the vector to be multiplied by the transpose of the matrix
2785 - v2  - the vector to be added to the result
2786 
2787   Output Parameter:
2788 . v3 - the result
2789 
2790   Level: beginner
2791 
2792   Note:
2793   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2794   call `MatMultTransposeAdd`(A,v1,v2,v1).
2795 
2796 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2797 @*/
2798 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2799 {
2800   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2801 
2802   PetscFunctionBegin;
2803   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2804   PetscValidType(mat, 1);
2805   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2806   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2807   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2808 
2809   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2810   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2811   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);
2812   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);
2813   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);
2814   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2815   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2816   MatCheckPreallocated(mat, 1);
2817 
2818   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2819   PetscCall(VecLockReadPush(v1));
2820   PetscCall((*op)(mat, v1, v2, v3));
2821   PetscCall(VecLockReadPop(v1));
2822   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2823   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2824   PetscFunctionReturn(PETSC_SUCCESS);
2825 }
2826 
2827 /*@
2828   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2829 
2830   Neighbor-wise Collective
2831 
2832   Input Parameters:
2833 + mat - the matrix
2834 . v1  - the vector to be multiplied by the Hermitian transpose
2835 - v2  - the vector to be added to the result
2836 
2837   Output Parameter:
2838 . v3 - the result
2839 
2840   Level: beginner
2841 
2842   Note:
2843   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2844   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2845 
2846 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2847 @*/
2848 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2849 {
2850   PetscFunctionBegin;
2851   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2852   PetscValidType(mat, 1);
2853   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2854   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2855   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2856 
2857   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2858   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2859   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2860   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);
2861   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);
2862   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);
2863   MatCheckPreallocated(mat, 1);
2864 
2865   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2866   PetscCall(VecLockReadPush(v1));
2867   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2868   else {
2869     Vec w, z;
2870     PetscCall(VecDuplicate(v1, &w));
2871     PetscCall(VecCopy(v1, w));
2872     PetscCall(VecConjugate(w));
2873     PetscCall(VecDuplicate(v3, &z));
2874     PetscCall(MatMultTranspose(mat, w, z));
2875     PetscCall(VecDestroy(&w));
2876     PetscCall(VecConjugate(z));
2877     if (v2 != v3) {
2878       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2879     } else {
2880       PetscCall(VecAXPY(v3, 1.0, z));
2881     }
2882     PetscCall(VecDestroy(&z));
2883   }
2884   PetscCall(VecLockReadPop(v1));
2885   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2886   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2887   PetscFunctionReturn(PETSC_SUCCESS);
2888 }
2889 
2890 /*@C
2891   MatGetFactorType - gets the type of factorization a matrix is
2892 
2893   Not Collective
2894 
2895   Input Parameter:
2896 . mat - the matrix
2897 
2898   Output Parameter:
2899 . 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`
2900 
2901   Level: intermediate
2902 
2903 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2904           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2905 @*/
2906 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2907 {
2908   PetscFunctionBegin;
2909   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2910   PetscValidType(mat, 1);
2911   PetscAssertPointer(t, 2);
2912   *t = mat->factortype;
2913   PetscFunctionReturn(PETSC_SUCCESS);
2914 }
2915 
2916 /*@C
2917   MatSetFactorType - sets the type of factorization a matrix is
2918 
2919   Logically Collective
2920 
2921   Input Parameters:
2922 + mat - the matrix
2923 - 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`
2924 
2925   Level: intermediate
2926 
2927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2928           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2929 @*/
2930 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2931 {
2932   PetscFunctionBegin;
2933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2934   PetscValidType(mat, 1);
2935   mat->factortype = t;
2936   PetscFunctionReturn(PETSC_SUCCESS);
2937 }
2938 
2939 /*@C
2940   MatGetInfo - Returns information about matrix storage (number of
2941   nonzeros, memory, etc.).
2942 
2943   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2944 
2945   Input Parameters:
2946 + mat  - the matrix
2947 - 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)
2948 
2949   Output Parameter:
2950 . info - matrix information context
2951 
2952   Options Database Key:
2953 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2954 
2955   Notes:
2956   The `MatInfo` context contains a variety of matrix data, including
2957   number of nonzeros allocated and used, number of mallocs during
2958   matrix assembly, etc.  Additional information for factored matrices
2959   is provided (such as the fill ratio, number of mallocs during
2960   factorization, etc.).
2961 
2962   Example:
2963   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2964   data within the MatInfo context.  For example,
2965 .vb
2966       MatInfo info;
2967       Mat     A;
2968       double  mal, nz_a, nz_u;
2969 
2970       MatGetInfo(A, MAT_LOCAL, &info);
2971       mal  = info.mallocs;
2972       nz_a = info.nz_allocated;
2973 .ve
2974 
2975   Fortran users should declare info as a double precision
2976   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2977   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2978   a complete list of parameter names.
2979 .vb
2980       double  precision info(MAT_INFO_SIZE)
2981       double  precision mal, nz_a
2982       Mat     A
2983       integer ierr
2984 
2985       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2986       mal = info(MAT_INFO_MALLOCS)
2987       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2988 .ve
2989 
2990   Level: intermediate
2991 
2992   Developer Note:
2993   The Fortran interface is not autogenerated as the
2994   interface definition cannot be generated correctly [due to `MatInfo` argument]
2995 
2996 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2997 @*/
2998 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2999 {
3000   PetscFunctionBegin;
3001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3002   PetscValidType(mat, 1);
3003   PetscAssertPointer(info, 3);
3004   MatCheckPreallocated(mat, 1);
3005   PetscUseTypeMethod(mat, getinfo, flag, info);
3006   PetscFunctionReturn(PETSC_SUCCESS);
3007 }
3008 
3009 /*
3010    This is used by external packages where it is not easy to get the info from the actual
3011    matrix factorization.
3012 */
3013 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3014 {
3015   PetscFunctionBegin;
3016   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3017   PetscFunctionReturn(PETSC_SUCCESS);
3018 }
3019 
3020 /*@C
3021   MatLUFactor - Performs in-place LU factorization of matrix.
3022 
3023   Collective
3024 
3025   Input Parameters:
3026 + mat  - the matrix
3027 . row  - row permutation
3028 . col  - column permutation
3029 - info - options for factorization, includes
3030 .vb
3031           fill - expected fill as ratio of original fill.
3032           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3033                    Run with the option -info to determine an optimal value to use
3034 .ve
3035 
3036   Level: developer
3037 
3038   Notes:
3039   Most users should employ the `KSP` interface for linear solvers
3040   instead of working directly with matrix algebra routines such as this.
3041   See, e.g., `KSPCreate()`.
3042 
3043   This changes the state of the matrix to a factored matrix; it cannot be used
3044   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3045 
3046   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3047   when not using `KSP`.
3048 
3049   Developer Note:
3050   The Fortran interface is not autogenerated as the
3051   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3052 
3053 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3054           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3055 @*/
3056 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3057 {
3058   MatFactorInfo tinfo;
3059 
3060   PetscFunctionBegin;
3061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3062   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3063   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3064   if (info) PetscAssertPointer(info, 4);
3065   PetscValidType(mat, 1);
3066   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3067   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3068   MatCheckPreallocated(mat, 1);
3069   if (!info) {
3070     PetscCall(MatFactorInfoInitialize(&tinfo));
3071     info = &tinfo;
3072   }
3073 
3074   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3075   PetscUseTypeMethod(mat, lufactor, row, col, info);
3076   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3077   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3078   PetscFunctionReturn(PETSC_SUCCESS);
3079 }
3080 
3081 /*@C
3082   MatILUFactor - Performs in-place ILU factorization of matrix.
3083 
3084   Collective
3085 
3086   Input Parameters:
3087 + mat  - the matrix
3088 . row  - row permutation
3089 . col  - column permutation
3090 - info - structure containing
3091 .vb
3092       levels - number of levels of fill.
3093       expected fill - as ratio of original fill.
3094       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3095                 missing diagonal entries)
3096 .ve
3097 
3098   Level: developer
3099 
3100   Notes:
3101   Most users should employ the `KSP` interface for linear solvers
3102   instead of working directly with matrix algebra routines such as this.
3103   See, e.g., `KSPCreate()`.
3104 
3105   Probably really in-place only when level of fill is zero, otherwise allocates
3106   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3107   when not using `KSP`.
3108 
3109   Developer Note:
3110   The Fortran interface is not autogenerated as the
3111   interface definition cannot be generated correctly [due to MatFactorInfo]
3112 
3113 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3114 @*/
3115 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3116 {
3117   PetscFunctionBegin;
3118   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3119   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3120   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3121   PetscAssertPointer(info, 4);
3122   PetscValidType(mat, 1);
3123   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3124   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3125   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3126   MatCheckPreallocated(mat, 1);
3127 
3128   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3129   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3130   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3131   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3132   PetscFunctionReturn(PETSC_SUCCESS);
3133 }
3134 
3135 /*@C
3136   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3137   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3138 
3139   Collective
3140 
3141   Input Parameters:
3142 + fact - the factor matrix obtained with `MatGetFactor()`
3143 . mat  - the matrix
3144 . row  - the row permutation
3145 . col  - the column permutation
3146 - info - options for factorization, includes
3147 .vb
3148           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3149           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3150 .ve
3151 
3152   Level: developer
3153 
3154   Notes:
3155   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3156 
3157   Most users should employ the simplified `KSP` interface for linear solvers
3158   instead of working directly with matrix algebra routines such as this.
3159   See, e.g., `KSPCreate()`.
3160 
3161   Developer Note:
3162   The Fortran interface is not autogenerated as the
3163   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3164 
3165 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3166 @*/
3167 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3168 {
3169   MatFactorInfo tinfo;
3170 
3171   PetscFunctionBegin;
3172   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3173   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3174   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3175   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3176   if (info) PetscAssertPointer(info, 5);
3177   PetscValidType(fact, 1);
3178   PetscValidType(mat, 2);
3179   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3180   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3181   MatCheckPreallocated(mat, 2);
3182   if (!info) {
3183     PetscCall(MatFactorInfoInitialize(&tinfo));
3184     info = &tinfo;
3185   }
3186 
3187   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3188   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3189   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3190   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3191   PetscFunctionReturn(PETSC_SUCCESS);
3192 }
3193 
3194 /*@C
3195   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3196   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3197 
3198   Collective
3199 
3200   Input Parameters:
3201 + fact - the factor matrix obtained with `MatGetFactor()`
3202 . mat  - the matrix
3203 - info - options for factorization
3204 
3205   Level: developer
3206 
3207   Notes:
3208   See `MatLUFactor()` for in-place factorization.  See
3209   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3210 
3211   Most users should employ the `KSP` interface for linear solvers
3212   instead of working directly with matrix algebra routines such as this.
3213   See, e.g., `KSPCreate()`.
3214 
3215   Developer Note:
3216   The Fortran interface is not autogenerated as the
3217   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3218 
3219 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3220 @*/
3221 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3222 {
3223   MatFactorInfo tinfo;
3224 
3225   PetscFunctionBegin;
3226   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3227   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3228   PetscValidType(fact, 1);
3229   PetscValidType(mat, 2);
3230   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3231   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,
3232              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3233 
3234   MatCheckPreallocated(mat, 2);
3235   if (!info) {
3236     PetscCall(MatFactorInfoInitialize(&tinfo));
3237     info = &tinfo;
3238   }
3239 
3240   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3241   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3242   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3243   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3244   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3245   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3246   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3247   PetscFunctionReturn(PETSC_SUCCESS);
3248 }
3249 
3250 /*@C
3251   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3252   symmetric matrix.
3253 
3254   Collective
3255 
3256   Input Parameters:
3257 + mat  - the matrix
3258 . perm - row and column permutations
3259 - info - expected fill as ratio of original fill
3260 
3261   Level: developer
3262 
3263   Notes:
3264   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3265   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3266 
3267   Most users should employ the `KSP` interface for linear solvers
3268   instead of working directly with matrix algebra routines such as this.
3269   See, e.g., `KSPCreate()`.
3270 
3271   Developer Note:
3272   The Fortran interface is not autogenerated as the
3273   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3274 
3275 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3276           `MatGetOrdering()`
3277 @*/
3278 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3279 {
3280   MatFactorInfo tinfo;
3281 
3282   PetscFunctionBegin;
3283   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3284   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3285   if (info) PetscAssertPointer(info, 3);
3286   PetscValidType(mat, 1);
3287   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3288   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3289   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3290   MatCheckPreallocated(mat, 1);
3291   if (!info) {
3292     PetscCall(MatFactorInfoInitialize(&tinfo));
3293     info = &tinfo;
3294   }
3295 
3296   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3297   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3298   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3299   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3300   PetscFunctionReturn(PETSC_SUCCESS);
3301 }
3302 
3303 /*@C
3304   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3305   of a symmetric matrix.
3306 
3307   Collective
3308 
3309   Input Parameters:
3310 + fact - the factor matrix obtained with `MatGetFactor()`
3311 . mat  - the matrix
3312 . perm - row and column permutations
3313 - info - options for factorization, includes
3314 .vb
3315           fill - expected fill as ratio of original fill.
3316           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3317                    Run with the option -info to determine an optimal value to use
3318 .ve
3319 
3320   Level: developer
3321 
3322   Notes:
3323   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3324   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3325 
3326   Most users should employ the `KSP` interface for linear solvers
3327   instead of working directly with matrix algebra routines such as this.
3328   See, e.g., `KSPCreate()`.
3329 
3330   Developer Note:
3331   The Fortran interface is not autogenerated as the
3332   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3333 
3334 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3335           `MatGetOrdering()`
3336 @*/
3337 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3338 {
3339   MatFactorInfo tinfo;
3340 
3341   PetscFunctionBegin;
3342   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3343   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3344   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3345   if (info) PetscAssertPointer(info, 4);
3346   PetscValidType(fact, 1);
3347   PetscValidType(mat, 2);
3348   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3349   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3350   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3351   MatCheckPreallocated(mat, 2);
3352   if (!info) {
3353     PetscCall(MatFactorInfoInitialize(&tinfo));
3354     info = &tinfo;
3355   }
3356 
3357   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3358   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3359   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3360   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3361   PetscFunctionReturn(PETSC_SUCCESS);
3362 }
3363 
3364 /*@C
3365   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3366   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3367   `MatCholeskyFactorSymbolic()`.
3368 
3369   Collective
3370 
3371   Input Parameters:
3372 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3373 . mat  - the initial matrix that is to be factored
3374 - info - options for factorization
3375 
3376   Level: developer
3377 
3378   Note:
3379   Most users should employ the `KSP` interface for linear solvers
3380   instead of working directly with matrix algebra routines such as this.
3381   See, e.g., `KSPCreate()`.
3382 
3383   Developer Note:
3384   The Fortran interface is not autogenerated as the
3385   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3386 
3387 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3388 @*/
3389 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3390 {
3391   MatFactorInfo tinfo;
3392 
3393   PetscFunctionBegin;
3394   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3395   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3396   PetscValidType(fact, 1);
3397   PetscValidType(mat, 2);
3398   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3399   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,
3400              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3401   MatCheckPreallocated(mat, 2);
3402   if (!info) {
3403     PetscCall(MatFactorInfoInitialize(&tinfo));
3404     info = &tinfo;
3405   }
3406 
3407   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3408   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3409   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3410   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3411   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3412   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3413   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3414   PetscFunctionReturn(PETSC_SUCCESS);
3415 }
3416 
3417 /*@
3418   MatQRFactor - Performs in-place QR factorization of matrix.
3419 
3420   Collective
3421 
3422   Input Parameters:
3423 + mat  - the matrix
3424 . col  - column permutation
3425 - info - options for factorization, includes
3426 .vb
3427           fill - expected fill as ratio of original fill.
3428           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3429                    Run with the option -info to determine an optimal value to use
3430 .ve
3431 
3432   Level: developer
3433 
3434   Notes:
3435   Most users should employ the `KSP` interface for linear solvers
3436   instead of working directly with matrix algebra routines such as this.
3437   See, e.g., `KSPCreate()`.
3438 
3439   This changes the state of the matrix to a factored matrix; it cannot be used
3440   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3441 
3442   Developer Note:
3443   The Fortran interface is not autogenerated as the
3444   interface definition cannot be generated correctly [due to MatFactorInfo]
3445 
3446 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3447           `MatSetUnfactored()`
3448 @*/
3449 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3450 {
3451   PetscFunctionBegin;
3452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3453   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3454   if (info) PetscAssertPointer(info, 3);
3455   PetscValidType(mat, 1);
3456   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3457   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3458   MatCheckPreallocated(mat, 1);
3459   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3460   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3461   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3462   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3463   PetscFunctionReturn(PETSC_SUCCESS);
3464 }
3465 
3466 /*@
3467   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3468   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3469 
3470   Collective
3471 
3472   Input Parameters:
3473 + fact - the factor matrix obtained with `MatGetFactor()`
3474 . mat  - the matrix
3475 . col  - column permutation
3476 - info - options for factorization, includes
3477 .vb
3478           fill - expected fill as ratio of original fill.
3479           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3480                    Run with the option -info to determine an optimal value to use
3481 .ve
3482 
3483   Level: developer
3484 
3485   Note:
3486   Most users should employ the `KSP` interface for linear solvers
3487   instead of working directly with matrix algebra routines such as this.
3488   See, e.g., `KSPCreate()`.
3489 
3490   Developer Note:
3491   The Fortran interface is not autogenerated as the
3492   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3493 
3494 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3495 @*/
3496 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3497 {
3498   MatFactorInfo tinfo;
3499 
3500   PetscFunctionBegin;
3501   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3503   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3504   if (info) PetscAssertPointer(info, 4);
3505   PetscValidType(fact, 1);
3506   PetscValidType(mat, 2);
3507   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3508   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3509   MatCheckPreallocated(mat, 2);
3510   if (!info) {
3511     PetscCall(MatFactorInfoInitialize(&tinfo));
3512     info = &tinfo;
3513   }
3514 
3515   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3516   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3517   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3518   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3519   PetscFunctionReturn(PETSC_SUCCESS);
3520 }
3521 
3522 /*@
3523   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3524   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3525 
3526   Collective
3527 
3528   Input Parameters:
3529 + fact - the factor matrix obtained with `MatGetFactor()`
3530 . mat  - the matrix
3531 - info - options for factorization
3532 
3533   Level: developer
3534 
3535   Notes:
3536   See `MatQRFactor()` for in-place factorization.
3537 
3538   Most users should employ the `KSP` interface for linear solvers
3539   instead of working directly with matrix algebra routines such as this.
3540   See, e.g., `KSPCreate()`.
3541 
3542   Developer Note:
3543   The Fortran interface is not autogenerated as the
3544   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3545 
3546 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3547 @*/
3548 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3549 {
3550   MatFactorInfo tinfo;
3551 
3552   PetscFunctionBegin;
3553   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3555   PetscValidType(fact, 1);
3556   PetscValidType(mat, 2);
3557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3558   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,
3559              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3560 
3561   MatCheckPreallocated(mat, 2);
3562   if (!info) {
3563     PetscCall(MatFactorInfoInitialize(&tinfo));
3564     info = &tinfo;
3565   }
3566 
3567   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3568   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3569   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3570   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3571   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3572   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3573   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3574   PetscFunctionReturn(PETSC_SUCCESS);
3575 }
3576 
3577 /*@
3578   MatSolve - Solves $A x = b$, given a factored matrix.
3579 
3580   Neighbor-wise Collective
3581 
3582   Input Parameters:
3583 + mat - the factored matrix
3584 - b   - the right-hand-side vector
3585 
3586   Output Parameter:
3587 . x - the result vector
3588 
3589   Level: developer
3590 
3591   Notes:
3592   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3593   call `MatSolve`(A,x,x).
3594 
3595   Most users should employ the `KSP` interface for linear solvers
3596   instead of working directly with matrix algebra routines such as this.
3597   See, e.g., `KSPCreate()`.
3598 
3599 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3600 @*/
3601 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3602 {
3603   PetscFunctionBegin;
3604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3605   PetscValidType(mat, 1);
3606   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3607   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3608   PetscCheckSameComm(mat, 1, b, 2);
3609   PetscCheckSameComm(mat, 1, x, 3);
3610   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3611   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);
3612   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);
3613   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);
3614   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3615   MatCheckPreallocated(mat, 1);
3616 
3617   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3618   if (mat->factorerrortype) {
3619     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3620     PetscCall(VecSetInf(x));
3621   } else PetscUseTypeMethod(mat, solve, b, x);
3622   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3623   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3624   PetscFunctionReturn(PETSC_SUCCESS);
3625 }
3626 
3627 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3628 {
3629   Vec      b, x;
3630   PetscInt N, i;
3631   PetscErrorCode (*f)(Mat, Vec, Vec);
3632   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3633 
3634   PetscFunctionBegin;
3635   if (A->factorerrortype) {
3636     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3637     PetscCall(MatSetInf(X));
3638     PetscFunctionReturn(PETSC_SUCCESS);
3639   }
3640   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3641   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3642   PetscCall(MatBoundToCPU(A, &Abound));
3643   if (!Abound) {
3644     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3645     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3646   }
3647 #if PetscDefined(HAVE_CUDA)
3648   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3649   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3650 #elif PetscDefined(HAVE_HIP)
3651   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3652   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3653 #endif
3654   PetscCall(MatGetSize(B, NULL, &N));
3655   for (i = 0; i < N; i++) {
3656     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3657     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3658     PetscCall((*f)(A, b, x));
3659     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3660     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3661   }
3662   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3663   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3664   PetscFunctionReturn(PETSC_SUCCESS);
3665 }
3666 
3667 /*@
3668   MatMatSolve - Solves $A X = B$, given a factored matrix.
3669 
3670   Neighbor-wise Collective
3671 
3672   Input Parameters:
3673 + A - the factored matrix
3674 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3675 
3676   Output Parameter:
3677 . X - the result matrix (dense matrix)
3678 
3679   Level: developer
3680 
3681   Note:
3682   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3683   otherwise, `B` and `X` cannot be the same.
3684 
3685 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3686 @*/
3687 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3688 {
3689   PetscFunctionBegin;
3690   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3691   PetscValidType(A, 1);
3692   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3693   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3694   PetscCheckSameComm(A, 1, B, 2);
3695   PetscCheckSameComm(A, 1, X, 3);
3696   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);
3697   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);
3698   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");
3699   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3700   MatCheckPreallocated(A, 1);
3701 
3702   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3703   if (!A->ops->matsolve) {
3704     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3705     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3706   } else PetscUseTypeMethod(A, matsolve, B, X);
3707   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3708   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3709   PetscFunctionReturn(PETSC_SUCCESS);
3710 }
3711 
3712 /*@
3713   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3714 
3715   Neighbor-wise Collective
3716 
3717   Input Parameters:
3718 + A - the factored matrix
3719 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3720 
3721   Output Parameter:
3722 . X - the result matrix (dense matrix)
3723 
3724   Level: developer
3725 
3726   Note:
3727   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3728   call `MatMatSolveTranspose`(A,X,X).
3729 
3730 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3731 @*/
3732 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3733 {
3734   PetscFunctionBegin;
3735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3736   PetscValidType(A, 1);
3737   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3738   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3739   PetscCheckSameComm(A, 1, B, 2);
3740   PetscCheckSameComm(A, 1, X, 3);
3741   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3742   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);
3743   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);
3744   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);
3745   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");
3746   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3747   MatCheckPreallocated(A, 1);
3748 
3749   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3750   if (!A->ops->matsolvetranspose) {
3751     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3752     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3753   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3754   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3755   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3756   PetscFunctionReturn(PETSC_SUCCESS);
3757 }
3758 
3759 /*@
3760   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3761 
3762   Neighbor-wise Collective
3763 
3764   Input Parameters:
3765 + A  - the factored matrix
3766 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3767 
3768   Output Parameter:
3769 . X - the result matrix (dense matrix)
3770 
3771   Level: developer
3772 
3773   Note:
3774   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
3775   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3776 
3777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3778 @*/
3779 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3780 {
3781   PetscFunctionBegin;
3782   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3783   PetscValidType(A, 1);
3784   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3785   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3786   PetscCheckSameComm(A, 1, Bt, 2);
3787   PetscCheckSameComm(A, 1, X, 3);
3788 
3789   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3790   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);
3791   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);
3792   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");
3793   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3794   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3795   MatCheckPreallocated(A, 1);
3796 
3797   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3798   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3799   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3800   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3801   PetscFunctionReturn(PETSC_SUCCESS);
3802 }
3803 
3804 /*@
3805   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3806   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3807 
3808   Neighbor-wise Collective
3809 
3810   Input Parameters:
3811 + mat - the factored matrix
3812 - b   - the right-hand-side vector
3813 
3814   Output Parameter:
3815 . x - the result vector
3816 
3817   Level: developer
3818 
3819   Notes:
3820   `MatSolve()` should be used for most applications, as it performs
3821   a forward solve followed by a backward solve.
3822 
3823   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3824   call `MatForwardSolve`(A,x,x).
3825 
3826   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3827   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3828   `MatForwardSolve()` solves $U^T*D y = b$, and
3829   `MatBackwardSolve()` solves $U x = y$.
3830   Thus they do not provide a symmetric preconditioner.
3831 
3832 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3833 @*/
3834 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3835 {
3836   PetscFunctionBegin;
3837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3838   PetscValidType(mat, 1);
3839   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3840   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3841   PetscCheckSameComm(mat, 1, b, 2);
3842   PetscCheckSameComm(mat, 1, x, 3);
3843   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3844   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);
3845   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);
3846   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);
3847   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3848   MatCheckPreallocated(mat, 1);
3849 
3850   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3851   PetscUseTypeMethod(mat, forwardsolve, b, x);
3852   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3853   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3854   PetscFunctionReturn(PETSC_SUCCESS);
3855 }
3856 
3857 /*@
3858   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3859   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3860 
3861   Neighbor-wise Collective
3862 
3863   Input Parameters:
3864 + mat - the factored matrix
3865 - b   - the right-hand-side vector
3866 
3867   Output Parameter:
3868 . x - the result vector
3869 
3870   Level: developer
3871 
3872   Notes:
3873   `MatSolve()` should be used for most applications, as it performs
3874   a forward solve followed by a backward solve.
3875 
3876   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3877   call `MatBackwardSolve`(A,x,x).
3878 
3879   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3880   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3881   `MatForwardSolve()` solves $U^T*D y = b$, and
3882   `MatBackwardSolve()` solves $U x = y$.
3883   Thus they do not provide a symmetric preconditioner.
3884 
3885 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3886 @*/
3887 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3888 {
3889   PetscFunctionBegin;
3890   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3891   PetscValidType(mat, 1);
3892   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3893   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3894   PetscCheckSameComm(mat, 1, b, 2);
3895   PetscCheckSameComm(mat, 1, x, 3);
3896   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3897   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);
3898   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);
3899   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);
3900   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3901   MatCheckPreallocated(mat, 1);
3902 
3903   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3904   PetscUseTypeMethod(mat, backwardsolve, b, x);
3905   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3906   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3907   PetscFunctionReturn(PETSC_SUCCESS);
3908 }
3909 
3910 /*@
3911   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3912 
3913   Neighbor-wise Collective
3914 
3915   Input Parameters:
3916 + mat - the factored matrix
3917 . b   - the right-hand-side vector
3918 - y   - the vector to be added to
3919 
3920   Output Parameter:
3921 . x - the result vector
3922 
3923   Level: developer
3924 
3925   Note:
3926   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3927   call `MatSolveAdd`(A,x,y,x).
3928 
3929 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3930 @*/
3931 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3932 {
3933   PetscScalar one = 1.0;
3934   Vec         tmp;
3935 
3936   PetscFunctionBegin;
3937   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3938   PetscValidType(mat, 1);
3939   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3940   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3941   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3942   PetscCheckSameComm(mat, 1, b, 2);
3943   PetscCheckSameComm(mat, 1, y, 3);
3944   PetscCheckSameComm(mat, 1, x, 4);
3945   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3946   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);
3947   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);
3948   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);
3949   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);
3950   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);
3951   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3952   MatCheckPreallocated(mat, 1);
3953 
3954   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3955   if (mat->factorerrortype) {
3956     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3957     PetscCall(VecSetInf(x));
3958   } else if (mat->ops->solveadd) {
3959     PetscUseTypeMethod(mat, solveadd, b, y, x);
3960   } else {
3961     /* do the solve then the add manually */
3962     if (x != y) {
3963       PetscCall(MatSolve(mat, b, x));
3964       PetscCall(VecAXPY(x, one, y));
3965     } else {
3966       PetscCall(VecDuplicate(x, &tmp));
3967       PetscCall(VecCopy(x, tmp));
3968       PetscCall(MatSolve(mat, b, x));
3969       PetscCall(VecAXPY(x, one, tmp));
3970       PetscCall(VecDestroy(&tmp));
3971     }
3972   }
3973   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3974   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3975   PetscFunctionReturn(PETSC_SUCCESS);
3976 }
3977 
3978 /*@
3979   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3980 
3981   Neighbor-wise Collective
3982 
3983   Input Parameters:
3984 + mat - the factored matrix
3985 - b   - the right-hand-side vector
3986 
3987   Output Parameter:
3988 . x - the result vector
3989 
3990   Level: developer
3991 
3992   Notes:
3993   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3994   call `MatSolveTranspose`(A,x,x).
3995 
3996   Most users should employ the `KSP` interface for linear solvers
3997   instead of working directly with matrix algebra routines such as this.
3998   See, e.g., `KSPCreate()`.
3999 
4000 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4001 @*/
4002 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4003 {
4004   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4005 
4006   PetscFunctionBegin;
4007   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4008   PetscValidType(mat, 1);
4009   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4010   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4011   PetscCheckSameComm(mat, 1, b, 2);
4012   PetscCheckSameComm(mat, 1, x, 3);
4013   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4014   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);
4015   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);
4016   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4017   MatCheckPreallocated(mat, 1);
4018   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4019   if (mat->factorerrortype) {
4020     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4021     PetscCall(VecSetInf(x));
4022   } else {
4023     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4024     PetscCall((*f)(mat, b, x));
4025   }
4026   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4027   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4028   PetscFunctionReturn(PETSC_SUCCESS);
4029 }
4030 
4031 /*@
4032   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4033   factored matrix.
4034 
4035   Neighbor-wise Collective
4036 
4037   Input Parameters:
4038 + mat - the factored matrix
4039 . b   - the right-hand-side vector
4040 - y   - the vector to be added to
4041 
4042   Output Parameter:
4043 . x - the result vector
4044 
4045   Level: developer
4046 
4047   Note:
4048   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4049   call `MatSolveTransposeAdd`(A,x,y,x).
4050 
4051 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4052 @*/
4053 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4054 {
4055   PetscScalar one = 1.0;
4056   Vec         tmp;
4057   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4058 
4059   PetscFunctionBegin;
4060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4061   PetscValidType(mat, 1);
4062   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4063   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4064   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4065   PetscCheckSameComm(mat, 1, b, 2);
4066   PetscCheckSameComm(mat, 1, y, 3);
4067   PetscCheckSameComm(mat, 1, x, 4);
4068   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4069   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);
4070   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);
4071   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);
4072   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);
4073   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4074   MatCheckPreallocated(mat, 1);
4075 
4076   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4077   if (mat->factorerrortype) {
4078     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4079     PetscCall(VecSetInf(x));
4080   } else if (f) {
4081     PetscCall((*f)(mat, b, y, x));
4082   } else {
4083     /* do the solve then the add manually */
4084     if (x != y) {
4085       PetscCall(MatSolveTranspose(mat, b, x));
4086       PetscCall(VecAXPY(x, one, y));
4087     } else {
4088       PetscCall(VecDuplicate(x, &tmp));
4089       PetscCall(VecCopy(x, tmp));
4090       PetscCall(MatSolveTranspose(mat, b, x));
4091       PetscCall(VecAXPY(x, one, tmp));
4092       PetscCall(VecDestroy(&tmp));
4093     }
4094   }
4095   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4096   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4097   PetscFunctionReturn(PETSC_SUCCESS);
4098 }
4099 
4100 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4101 /*@
4102   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4103 
4104   Neighbor-wise Collective
4105 
4106   Input Parameters:
4107 + mat   - the matrix
4108 . b     - the right hand side
4109 . omega - the relaxation factor
4110 . flag  - flag indicating the type of SOR (see below)
4111 . shift - diagonal shift
4112 . its   - the number of iterations
4113 - lits  - the number of local iterations
4114 
4115   Output Parameter:
4116 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4117 
4118   SOR Flags:
4119 +     `SOR_FORWARD_SWEEP` - forward SOR
4120 .     `SOR_BACKWARD_SWEEP` - backward SOR
4121 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4122 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4123 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4124 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4125 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4126 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4127   upper/lower triangular part of matrix to
4128   vector (with omega)
4129 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4130 
4131   Level: developer
4132 
4133   Notes:
4134   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4135   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4136   on each processor.
4137 
4138   Application programmers will not generally use `MatSOR()` directly,
4139   but instead will employ the `KSP`/`PC` interface.
4140 
4141   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4142 
4143   Most users should employ the `KSP` interface for linear solvers
4144   instead of working directly with matrix algebra routines such as this.
4145   See, e.g., `KSPCreate()`.
4146 
4147   Vectors `x` and `b` CANNOT be the same
4148 
4149   The flags are implemented as bitwise inclusive or operations.
4150   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4151   to specify a zero initial guess for SSOR.
4152 
4153   Developer Note:
4154   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4155 
4156 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4157 @*/
4158 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4159 {
4160   PetscFunctionBegin;
4161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4162   PetscValidType(mat, 1);
4163   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4164   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4165   PetscCheckSameComm(mat, 1, b, 2);
4166   PetscCheckSameComm(mat, 1, x, 8);
4167   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4168   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4169   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);
4170   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);
4171   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);
4172   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4173   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4174   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4175 
4176   MatCheckPreallocated(mat, 1);
4177   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4178   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4179   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4180   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4181   PetscFunctionReturn(PETSC_SUCCESS);
4182 }
4183 
4184 /*
4185       Default matrix copy routine.
4186 */
4187 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4188 {
4189   PetscInt           i, rstart = 0, rend = 0, nz;
4190   const PetscInt    *cwork;
4191   const PetscScalar *vwork;
4192 
4193   PetscFunctionBegin;
4194   if (B->assembled) PetscCall(MatZeroEntries(B));
4195   if (str == SAME_NONZERO_PATTERN) {
4196     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4197     for (i = rstart; i < rend; i++) {
4198       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4199       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4200       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4201     }
4202   } else {
4203     PetscCall(MatAYPX(B, 0.0, A, str));
4204   }
4205   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4206   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4207   PetscFunctionReturn(PETSC_SUCCESS);
4208 }
4209 
4210 /*@
4211   MatCopy - Copies a matrix to another matrix.
4212 
4213   Collective
4214 
4215   Input Parameters:
4216 + A   - the matrix
4217 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4218 
4219   Output Parameter:
4220 . B - where the copy is put
4221 
4222   Level: intermediate
4223 
4224   Notes:
4225   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4226 
4227   `MatCopy()` copies the matrix entries of a matrix to another existing
4228   matrix (after first zeroing the second matrix).  A related routine is
4229   `MatConvert()`, which first creates a new matrix and then copies the data.
4230 
4231 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4232 @*/
4233 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4234 {
4235   PetscInt i;
4236 
4237   PetscFunctionBegin;
4238   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4239   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4240   PetscValidType(A, 1);
4241   PetscValidType(B, 2);
4242   PetscCheckSameComm(A, 1, B, 2);
4243   MatCheckPreallocated(B, 2);
4244   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4245   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4246   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,
4247              A->cmap->N, B->cmap->N);
4248   MatCheckPreallocated(A, 1);
4249   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4250 
4251   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4252   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4253   else PetscCall(MatCopy_Basic(A, B, str));
4254 
4255   B->stencil.dim = A->stencil.dim;
4256   B->stencil.noc = A->stencil.noc;
4257   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4258     B->stencil.dims[i]   = A->stencil.dims[i];
4259     B->stencil.starts[i] = A->stencil.starts[i];
4260   }
4261 
4262   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4263   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4264   PetscFunctionReturn(PETSC_SUCCESS);
4265 }
4266 
4267 /*@C
4268   MatConvert - Converts a matrix to another matrix, either of the same
4269   or different type.
4270 
4271   Collective
4272 
4273   Input Parameters:
4274 + mat     - the matrix
4275 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4276    same type as the original matrix.
4277 - reuse   - denotes if the destination matrix is to be created or reused.
4278    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
4279    `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).
4280 
4281   Output Parameter:
4282 . M - pointer to place new matrix
4283 
4284   Level: intermediate
4285 
4286   Notes:
4287   `MatConvert()` first creates a new matrix and then copies the data from
4288   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4289   entries of one matrix to another already existing matrix context.
4290 
4291   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4292   the MPI communicator of the generated matrix is always the same as the communicator
4293   of the input matrix.
4294 
4295 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4296 @*/
4297 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4298 {
4299   PetscBool  sametype, issame, flg;
4300   PetscBool3 issymmetric, ishermitian;
4301   char       convname[256], mtype[256];
4302   Mat        B;
4303 
4304   PetscFunctionBegin;
4305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4306   PetscValidType(mat, 1);
4307   PetscAssertPointer(M, 4);
4308   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4309   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4310   MatCheckPreallocated(mat, 1);
4311 
4312   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4313   if (flg) newtype = mtype;
4314 
4315   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4316   PetscCall(PetscStrcmp(newtype, "same", &issame));
4317   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4318   if (reuse == MAT_REUSE_MATRIX) {
4319     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4320     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4321   }
4322 
4323   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4324     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4325     PetscFunctionReturn(PETSC_SUCCESS);
4326   }
4327 
4328   /* Cache Mat options because some converters use MatHeaderReplace  */
4329   issymmetric = mat->symmetric;
4330   ishermitian = mat->hermitian;
4331 
4332   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4333     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4334     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4335   } else {
4336     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4337     const char *prefix[3]                                 = {"seq", "mpi", ""};
4338     PetscInt    i;
4339     /*
4340        Order of precedence:
4341        0) See if newtype is a superclass of the current matrix.
4342        1) See if a specialized converter is known to the current matrix.
4343        2) See if a specialized converter is known to the desired matrix class.
4344        3) See if a good general converter is registered for the desired class
4345           (as of 6/27/03 only MATMPIADJ falls into this category).
4346        4) See if a good general converter is known for the current matrix.
4347        5) Use a really basic converter.
4348     */
4349 
4350     /* 0) See if newtype is a superclass of the current matrix.
4351           i.e mat is mpiaij and newtype is aij */
4352     for (i = 0; i < 2; i++) {
4353       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4354       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4355       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4356       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4357       if (flg) {
4358         if (reuse == MAT_INPLACE_MATRIX) {
4359           PetscCall(PetscInfo(mat, "Early return\n"));
4360           PetscFunctionReturn(PETSC_SUCCESS);
4361         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4362           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4363           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4364           PetscFunctionReturn(PETSC_SUCCESS);
4365         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4366           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4367           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4368           PetscFunctionReturn(PETSC_SUCCESS);
4369         }
4370       }
4371     }
4372     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4373     for (i = 0; i < 3; i++) {
4374       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4380       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4381       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4382       if (conv) goto foundconv;
4383     }
4384 
4385     /* 2)  See if a specialized converter is known to the desired matrix class. */
4386     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4387     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4388     PetscCall(MatSetType(B, newtype));
4389     for (i = 0; i < 3; i++) {
4390       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4396       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4397       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4398       if (conv) {
4399         PetscCall(MatDestroy(&B));
4400         goto foundconv;
4401       }
4402     }
4403 
4404     /* 3) See if a good general converter is registered for the desired class */
4405     conv = B->ops->convertfrom;
4406     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4407     PetscCall(MatDestroy(&B));
4408     if (conv) goto foundconv;
4409 
4410     /* 4) See if a good general converter is known for the current matrix */
4411     if (mat->ops->convert) conv = mat->ops->convert;
4412     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4413     if (conv) goto foundconv;
4414 
4415     /* 5) Use a really basic converter. */
4416     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4417     conv = MatConvert_Basic;
4418 
4419   foundconv:
4420     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4421     PetscCall((*conv)(mat, newtype, reuse, M));
4422     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4423       /* the block sizes must be same if the mappings are copied over */
4424       (*M)->rmap->bs = mat->rmap->bs;
4425       (*M)->cmap->bs = mat->cmap->bs;
4426       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4427       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4428       (*M)->rmap->mapping = mat->rmap->mapping;
4429       (*M)->cmap->mapping = mat->cmap->mapping;
4430     }
4431     (*M)->stencil.dim = mat->stencil.dim;
4432     (*M)->stencil.noc = mat->stencil.noc;
4433     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4434       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4435       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4436     }
4437     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4438   }
4439   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4440 
4441   /* Copy Mat options */
4442   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4443   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4444   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4445   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4446   PetscFunctionReturn(PETSC_SUCCESS);
4447 }
4448 
4449 /*@C
4450   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4451 
4452   Not Collective
4453 
4454   Input Parameter:
4455 . mat - the matrix, must be a factored matrix
4456 
4457   Output Parameter:
4458 . type - the string name of the package (do not free this string)
4459 
4460   Level: intermediate
4461 
4462   Fortran Note:
4463   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4464 
4465 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4466 @*/
4467 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4468 {
4469   PetscErrorCode (*conv)(Mat, MatSolverType *);
4470 
4471   PetscFunctionBegin;
4472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4473   PetscValidType(mat, 1);
4474   PetscAssertPointer(type, 2);
4475   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4476   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4477   if (conv) PetscCall((*conv)(mat, type));
4478   else *type = MATSOLVERPETSC;
4479   PetscFunctionReturn(PETSC_SUCCESS);
4480 }
4481 
4482 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4483 struct _MatSolverTypeForSpecifcType {
4484   MatType mtype;
4485   /* no entry for MAT_FACTOR_NONE */
4486   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4487   MatSolverTypeForSpecifcType next;
4488 };
4489 
4490 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4491 struct _MatSolverTypeHolder {
4492   char                       *name;
4493   MatSolverTypeForSpecifcType handlers;
4494   MatSolverTypeHolder         next;
4495 };
4496 
4497 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4498 
4499 /*@C
4500   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4501 
4502   Input Parameters:
4503 + package      - name of the package, for example petsc or superlu
4504 . mtype        - the matrix type that works with this package
4505 . ftype        - the type of factorization supported by the package
4506 - createfactor - routine that will create the factored matrix ready to be used
4507 
4508   Level: developer
4509 
4510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4511   `MatGetFactor()`
4512 @*/
4513 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4514 {
4515   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4516   PetscBool                   flg;
4517   MatSolverTypeForSpecifcType inext, iprev = NULL;
4518 
4519   PetscFunctionBegin;
4520   PetscCall(MatInitializePackage());
4521   if (!next) {
4522     PetscCall(PetscNew(&MatSolverTypeHolders));
4523     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4524     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4525     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4526     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4527     PetscFunctionReturn(PETSC_SUCCESS);
4528   }
4529   while (next) {
4530     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4531     if (flg) {
4532       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4533       inext = next->handlers;
4534       while (inext) {
4535         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4536         if (flg) {
4537           inext->createfactor[(int)ftype - 1] = createfactor;
4538           PetscFunctionReturn(PETSC_SUCCESS);
4539         }
4540         iprev = inext;
4541         inext = inext->next;
4542       }
4543       PetscCall(PetscNew(&iprev->next));
4544       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4545       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4546       PetscFunctionReturn(PETSC_SUCCESS);
4547     }
4548     prev = next;
4549     next = next->next;
4550   }
4551   PetscCall(PetscNew(&prev->next));
4552   PetscCall(PetscStrallocpy(package, &prev->next->name));
4553   PetscCall(PetscNew(&prev->next->handlers));
4554   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4555   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4556   PetscFunctionReturn(PETSC_SUCCESS);
4557 }
4558 
4559 /*@C
4560   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4561 
4562   Input Parameters:
4563 + type  - name of the package, for example petsc or superlu, if this is 'NULL' then the first result that satisfies the other criteria is returned
4564 . ftype - the type of factorization supported by the type
4565 - mtype - the matrix type that works with this type
4566 
4567   Output Parameters:
4568 + foundtype    - `PETSC_TRUE` if the type was registered
4569 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4570 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4571 
4572   Calling sequence of `createfactor`:
4573 + A     - the matrix providing the factor matrix
4574 . mtype - the `MatType` of the factor requested
4575 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4576 
4577   Level: developer
4578 
4579   Note:
4580   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4581   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4582   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4583 
4584 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4585           `MatInitializePackage()`
4586 @*/
4587 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4588 {
4589   MatSolverTypeHolder         next = MatSolverTypeHolders;
4590   PetscBool                   flg;
4591   MatSolverTypeForSpecifcType inext;
4592 
4593   PetscFunctionBegin;
4594   if (foundtype) *foundtype = PETSC_FALSE;
4595   if (foundmtype) *foundmtype = PETSC_FALSE;
4596   if (createfactor) *createfactor = NULL;
4597 
4598   if (type) {
4599     while (next) {
4600       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4601       if (flg) {
4602         if (foundtype) *foundtype = PETSC_TRUE;
4603         inext = next->handlers;
4604         while (inext) {
4605           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4606           if (flg) {
4607             if (foundmtype) *foundmtype = PETSC_TRUE;
4608             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4609             PetscFunctionReturn(PETSC_SUCCESS);
4610           }
4611           inext = inext->next;
4612         }
4613       }
4614       next = next->next;
4615     }
4616   } else {
4617     while (next) {
4618       inext = next->handlers;
4619       while (inext) {
4620         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4621         if (flg && inext->createfactor[(int)ftype - 1]) {
4622           if (foundtype) *foundtype = PETSC_TRUE;
4623           if (foundmtype) *foundmtype = PETSC_TRUE;
4624           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4625           PetscFunctionReturn(PETSC_SUCCESS);
4626         }
4627         inext = inext->next;
4628       }
4629       next = next->next;
4630     }
4631     /* try with base classes inext->mtype */
4632     next = MatSolverTypeHolders;
4633     while (next) {
4634       inext = next->handlers;
4635       while (inext) {
4636         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4637         if (flg && inext->createfactor[(int)ftype - 1]) {
4638           if (foundtype) *foundtype = PETSC_TRUE;
4639           if (foundmtype) *foundmtype = PETSC_TRUE;
4640           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4641           PetscFunctionReturn(PETSC_SUCCESS);
4642         }
4643         inext = inext->next;
4644       }
4645       next = next->next;
4646     }
4647   }
4648   PetscFunctionReturn(PETSC_SUCCESS);
4649 }
4650 
4651 PetscErrorCode MatSolverTypeDestroy(void)
4652 {
4653   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4654   MatSolverTypeForSpecifcType inext, iprev;
4655 
4656   PetscFunctionBegin;
4657   while (next) {
4658     PetscCall(PetscFree(next->name));
4659     inext = next->handlers;
4660     while (inext) {
4661       PetscCall(PetscFree(inext->mtype));
4662       iprev = inext;
4663       inext = inext->next;
4664       PetscCall(PetscFree(iprev));
4665     }
4666     prev = next;
4667     next = next->next;
4668     PetscCall(PetscFree(prev));
4669   }
4670   MatSolverTypeHolders = NULL;
4671   PetscFunctionReturn(PETSC_SUCCESS);
4672 }
4673 
4674 /*@C
4675   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4676 
4677   Logically Collective
4678 
4679   Input Parameter:
4680 . mat - the matrix
4681 
4682   Output Parameter:
4683 . flg - `PETSC_TRUE` if uses the ordering
4684 
4685   Level: developer
4686 
4687   Note:
4688   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4689   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4690 
4691 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4692 @*/
4693 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4694 {
4695   PetscFunctionBegin;
4696   *flg = mat->canuseordering;
4697   PetscFunctionReturn(PETSC_SUCCESS);
4698 }
4699 
4700 /*@C
4701   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4702 
4703   Logically Collective
4704 
4705   Input Parameters:
4706 + mat   - the matrix obtained with `MatGetFactor()`
4707 - ftype - the factorization type to be used
4708 
4709   Output Parameter:
4710 . otype - the preferred ordering type
4711 
4712   Level: developer
4713 
4714 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4715 @*/
4716 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4717 {
4718   PetscFunctionBegin;
4719   *otype = mat->preferredordering[ftype];
4720   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4721   PetscFunctionReturn(PETSC_SUCCESS);
4722 }
4723 
4724 /*@C
4725   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4726 
4727   Collective
4728 
4729   Input Parameters:
4730 + mat   - the matrix
4731 . 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
4732           the other criteria is returned
4733 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4734 
4735   Output Parameter:
4736 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4737 
4738   Options Database Keys:
4739 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4740 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4741                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4742 
4743   Level: intermediate
4744 
4745   Notes:
4746   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4747   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4748 
4749   Users usually access the factorization solvers via `KSP`
4750 
4751   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4752   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
4753 
4754   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4755   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4756   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4757 
4758   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4759   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4760   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4761 
4762   Developer Note:
4763   This should actually be called `MatCreateFactor()` since it creates a new factor object
4764 
4765 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4766           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4767           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4768 @*/
4769 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4770 {
4771   PetscBool foundtype, foundmtype;
4772   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4773 
4774   PetscFunctionBegin;
4775   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4776   PetscValidType(mat, 1);
4777 
4778   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4779   MatCheckPreallocated(mat, 1);
4780 
4781   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4782   if (!foundtype) {
4783     if (type) {
4784       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],
4785               ((PetscObject)mat)->type_name, type);
4786     } else {
4787       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);
4788     }
4789   }
4790   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4791   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);
4792 
4793   PetscCall((*conv)(mat, ftype, f));
4794   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4795   PetscFunctionReturn(PETSC_SUCCESS);
4796 }
4797 
4798 /*@C
4799   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4800 
4801   Not Collective
4802 
4803   Input Parameters:
4804 + mat   - the matrix
4805 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4806 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4807 
4808   Output Parameter:
4809 . flg - PETSC_TRUE if the factorization is available
4810 
4811   Level: intermediate
4812 
4813   Notes:
4814   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4815   such as pastix, superlu, mumps etc.
4816 
4817   PETSc must have been ./configure to use the external solver, using the option --download-package
4818 
4819   Developer Note:
4820   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4821 
4822 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4823           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4824 @*/
4825 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4826 {
4827   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4828 
4829   PetscFunctionBegin;
4830   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4831   PetscAssertPointer(flg, 4);
4832 
4833   *flg = PETSC_FALSE;
4834   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4835 
4836   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4837   MatCheckPreallocated(mat, 1);
4838 
4839   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4840   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4841   PetscFunctionReturn(PETSC_SUCCESS);
4842 }
4843 
4844 /*@
4845   MatDuplicate - Duplicates a matrix including the non-zero structure.
4846 
4847   Collective
4848 
4849   Input Parameters:
4850 + mat - the matrix
4851 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4852         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4853 
4854   Output Parameter:
4855 . M - pointer to place new matrix
4856 
4857   Level: intermediate
4858 
4859   Notes:
4860   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4861 
4862   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4863 
4864   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.
4865 
4866   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4867   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4868   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4869 
4870 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4871 @*/
4872 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4873 {
4874   Mat         B;
4875   VecType     vtype;
4876   PetscInt    i;
4877   PetscObject dm, container_h, container_d;
4878   void (*viewf)(void);
4879 
4880   PetscFunctionBegin;
4881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4882   PetscValidType(mat, 1);
4883   PetscAssertPointer(M, 3);
4884   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4885   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4886   MatCheckPreallocated(mat, 1);
4887 
4888   *M = NULL;
4889   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4890   PetscUseTypeMethod(mat, duplicate, op, M);
4891   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4892   B = *M;
4893 
4894   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4895   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4896   PetscCall(MatGetVecType(mat, &vtype));
4897   PetscCall(MatSetVecType(B, vtype));
4898 
4899   B->stencil.dim = mat->stencil.dim;
4900   B->stencil.noc = mat->stencil.noc;
4901   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4902     B->stencil.dims[i]   = mat->stencil.dims[i];
4903     B->stencil.starts[i] = mat->stencil.starts[i];
4904   }
4905 
4906   B->nooffproczerorows = mat->nooffproczerorows;
4907   B->nooffprocentries  = mat->nooffprocentries;
4908 
4909   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4910   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4911   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4912   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4913   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4914   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4915   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4916   PetscFunctionReturn(PETSC_SUCCESS);
4917 }
4918 
4919 /*@
4920   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4921 
4922   Logically Collective
4923 
4924   Input Parameter:
4925 . mat - the matrix
4926 
4927   Output Parameter:
4928 . v - the diagonal of the matrix
4929 
4930   Level: intermediate
4931 
4932   Note:
4933   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4934   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4935   is larger than `ndiag`, the values of the remaining entries are unspecified.
4936 
4937   Currently only correct in parallel for square matrices.
4938 
4939 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4940 @*/
4941 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4942 {
4943   PetscFunctionBegin;
4944   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4945   PetscValidType(mat, 1);
4946   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4947   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4948   MatCheckPreallocated(mat, 1);
4949   if (PetscDefined(USE_DEBUG)) {
4950     PetscInt nv, row, col, ndiag;
4951 
4952     PetscCall(VecGetLocalSize(v, &nv));
4953     PetscCall(MatGetLocalSize(mat, &row, &col));
4954     ndiag = PetscMin(row, col);
4955     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);
4956   }
4957 
4958   PetscUseTypeMethod(mat, getdiagonal, v);
4959   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4960   PetscFunctionReturn(PETSC_SUCCESS);
4961 }
4962 
4963 /*@C
4964   MatGetRowMin - Gets the minimum value (of the real part) of each
4965   row of the matrix
4966 
4967   Logically Collective
4968 
4969   Input Parameter:
4970 . mat - the matrix
4971 
4972   Output Parameters:
4973 + v   - the vector for storing the maximums
4974 - idx - the indices of the column found for each row (optional)
4975 
4976   Level: intermediate
4977 
4978   Note:
4979   The result of this call are the same as if one converted the matrix to dense format
4980   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4981 
4982   This code is only implemented for a couple of matrix formats.
4983 
4984 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4985           `MatGetRowMax()`
4986 @*/
4987 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4988 {
4989   PetscFunctionBegin;
4990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4991   PetscValidType(mat, 1);
4992   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4993   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4994 
4995   if (!mat->cmap->N) {
4996     PetscCall(VecSet(v, PETSC_MAX_REAL));
4997     if (idx) {
4998       PetscInt i, m = mat->rmap->n;
4999       for (i = 0; i < m; i++) idx[i] = -1;
5000     }
5001   } else {
5002     MatCheckPreallocated(mat, 1);
5003   }
5004   PetscUseTypeMethod(mat, getrowmin, v, idx);
5005   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5006   PetscFunctionReturn(PETSC_SUCCESS);
5007 }
5008 
5009 /*@C
5010   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5011   row of the matrix
5012 
5013   Logically Collective
5014 
5015   Input Parameter:
5016 . mat - the matrix
5017 
5018   Output Parameters:
5019 + v   - the vector for storing the minimums
5020 - idx - the indices of the column found for each row (or `NULL` if not needed)
5021 
5022   Level: intermediate
5023 
5024   Notes:
5025   if a row is completely empty or has only 0.0 values then the `idx` value for that
5026   row is 0 (the first column).
5027 
5028   This code is only implemented for a couple of matrix formats.
5029 
5030 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5031 @*/
5032 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5033 {
5034   PetscFunctionBegin;
5035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5036   PetscValidType(mat, 1);
5037   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5038   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5039   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5040 
5041   if (!mat->cmap->N) {
5042     PetscCall(VecSet(v, 0.0));
5043     if (idx) {
5044       PetscInt i, m = mat->rmap->n;
5045       for (i = 0; i < m; i++) idx[i] = -1;
5046     }
5047   } else {
5048     MatCheckPreallocated(mat, 1);
5049     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5050     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5051   }
5052   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5053   PetscFunctionReturn(PETSC_SUCCESS);
5054 }
5055 
5056 /*@C
5057   MatGetRowMax - Gets the maximum value (of the real part) of each
5058   row of the matrix
5059 
5060   Logically Collective
5061 
5062   Input Parameter:
5063 . mat - the matrix
5064 
5065   Output Parameters:
5066 + v   - the vector for storing the maximums
5067 - idx - the indices of the column found for each row (optional)
5068 
5069   Level: intermediate
5070 
5071   Notes:
5072   The result of this call are the same as if one converted the matrix to dense format
5073   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5074 
5075   This code is only implemented for a couple of matrix formats.
5076 
5077 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5078 @*/
5079 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5080 {
5081   PetscFunctionBegin;
5082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5083   PetscValidType(mat, 1);
5084   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5085   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5086 
5087   if (!mat->cmap->N) {
5088     PetscCall(VecSet(v, PETSC_MIN_REAL));
5089     if (idx) {
5090       PetscInt i, m = mat->rmap->n;
5091       for (i = 0; i < m; i++) idx[i] = -1;
5092     }
5093   } else {
5094     MatCheckPreallocated(mat, 1);
5095     PetscUseTypeMethod(mat, getrowmax, v, idx);
5096   }
5097   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5098   PetscFunctionReturn(PETSC_SUCCESS);
5099 }
5100 
5101 /*@C
5102   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5103   row of the matrix
5104 
5105   Logically Collective
5106 
5107   Input Parameter:
5108 . mat - the matrix
5109 
5110   Output Parameters:
5111 + v   - the vector for storing the maximums
5112 - idx - the indices of the column found for each row (or `NULL` if not needed)
5113 
5114   Level: intermediate
5115 
5116   Notes:
5117   if a row is completely empty or has only 0.0 values then the `idx` value for that
5118   row is 0 (the first column).
5119 
5120   This code is only implemented for a couple of matrix formats.
5121 
5122 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5123 @*/
5124 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5125 {
5126   PetscFunctionBegin;
5127   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5128   PetscValidType(mat, 1);
5129   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5130   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5131 
5132   if (!mat->cmap->N) {
5133     PetscCall(VecSet(v, 0.0));
5134     if (idx) {
5135       PetscInt i, m = mat->rmap->n;
5136       for (i = 0; i < m; i++) idx[i] = -1;
5137     }
5138   } else {
5139     MatCheckPreallocated(mat, 1);
5140     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5141     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5142   }
5143   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5144   PetscFunctionReturn(PETSC_SUCCESS);
5145 }
5146 
5147 /*@
5148   MatGetRowSum - Gets the sum of each row of the matrix
5149 
5150   Logically or Neighborhood Collective
5151 
5152   Input Parameter:
5153 . mat - the matrix
5154 
5155   Output Parameter:
5156 . v - the vector for storing the sum of rows
5157 
5158   Level: intermediate
5159 
5160   Note:
5161   This code is slow since it is not currently specialized for different formats
5162 
5163 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5164 @*/
5165 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5166 {
5167   Vec ones;
5168 
5169   PetscFunctionBegin;
5170   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5171   PetscValidType(mat, 1);
5172   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5173   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5174   MatCheckPreallocated(mat, 1);
5175   PetscCall(MatCreateVecs(mat, &ones, NULL));
5176   PetscCall(VecSet(ones, 1.));
5177   PetscCall(MatMult(mat, ones, v));
5178   PetscCall(VecDestroy(&ones));
5179   PetscFunctionReturn(PETSC_SUCCESS);
5180 }
5181 
5182 /*@
5183   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5184   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5185 
5186   Collective
5187 
5188   Input Parameter:
5189 . mat - the matrix to provide the transpose
5190 
5191   Output Parameter:
5192 . 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
5193 
5194   Level: advanced
5195 
5196   Note:
5197   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
5198   routine allows bypassing that call.
5199 
5200 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5201 @*/
5202 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5203 {
5204   PetscContainer  rB = NULL;
5205   MatParentState *rb = NULL;
5206 
5207   PetscFunctionBegin;
5208   PetscCall(PetscNew(&rb));
5209   rb->id    = ((PetscObject)mat)->id;
5210   rb->state = 0;
5211   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5212   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5213   PetscCall(PetscContainerSetPointer(rB, rb));
5214   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5215   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5216   PetscCall(PetscObjectDereference((PetscObject)rB));
5217   PetscFunctionReturn(PETSC_SUCCESS);
5218 }
5219 
5220 /*@
5221   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5222 
5223   Collective
5224 
5225   Input Parameters:
5226 + mat   - the matrix to transpose
5227 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5228 
5229   Output Parameter:
5230 . B - the transpose
5231 
5232   Level: intermediate
5233 
5234   Notes:
5235   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5236 
5237   `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
5238   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5239 
5240   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.
5241 
5242   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5243 
5244   If mat is unchanged from the last call this function returns immediately without recomputing the result
5245 
5246   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5247 
5248 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5249           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5250 @*/
5251 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5252 {
5253   PetscContainer  rB = NULL;
5254   MatParentState *rb = NULL;
5255 
5256   PetscFunctionBegin;
5257   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5258   PetscValidType(mat, 1);
5259   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5260   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5261   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5262   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5263   MatCheckPreallocated(mat, 1);
5264   if (reuse == MAT_REUSE_MATRIX) {
5265     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5266     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5267     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5268     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5269     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5270   }
5271 
5272   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5273   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5274     PetscUseTypeMethod(mat, transpose, reuse, B);
5275     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5276   }
5277   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5278 
5279   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5280   if (reuse != MAT_INPLACE_MATRIX) {
5281     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5282     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5283     rb->state        = ((PetscObject)mat)->state;
5284     rb->nonzerostate = mat->nonzerostate;
5285   }
5286   PetscFunctionReturn(PETSC_SUCCESS);
5287 }
5288 
5289 /*@
5290   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5291 
5292   Collective
5293 
5294   Input Parameter:
5295 . A - the matrix to transpose
5296 
5297   Output Parameter:
5298 . 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
5299       numerical portion.
5300 
5301   Level: intermediate
5302 
5303   Note:
5304   This is not supported for many matrix types, use `MatTranspose()` in those cases
5305 
5306 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5307 @*/
5308 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5309 {
5310   PetscFunctionBegin;
5311   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5312   PetscValidType(A, 1);
5313   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5314   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5315   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5316   PetscUseTypeMethod(A, transposesymbolic, B);
5317   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5318 
5319   PetscCall(MatTransposeSetPrecursor(A, *B));
5320   PetscFunctionReturn(PETSC_SUCCESS);
5321 }
5322 
5323 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5324 {
5325   PetscContainer  rB;
5326   MatParentState *rb;
5327 
5328   PetscFunctionBegin;
5329   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5330   PetscValidType(A, 1);
5331   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5332   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5333   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5334   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5335   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5336   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5337   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5338   PetscFunctionReturn(PETSC_SUCCESS);
5339 }
5340 
5341 /*@
5342   MatIsTranspose - Test whether a matrix is another one's transpose,
5343   or its own, in which case it tests symmetry.
5344 
5345   Collective
5346 
5347   Input Parameters:
5348 + A   - the matrix to test
5349 . B   - the matrix to test against, this can equal the first parameter
5350 - tol - tolerance, differences between entries smaller than this are counted as zero
5351 
5352   Output Parameter:
5353 . flg - the result
5354 
5355   Level: intermediate
5356 
5357   Notes:
5358   Only available for `MATAIJ` matrices.
5359 
5360   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5361   test involves parallel copies of the block off-diagonal parts of the matrix.
5362 
5363 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5364 @*/
5365 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5366 {
5367   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5368 
5369   PetscFunctionBegin;
5370   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5371   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5372   PetscAssertPointer(flg, 4);
5373   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5374   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5375   *flg = PETSC_FALSE;
5376   if (f && g) {
5377     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5378     PetscCall((*f)(A, B, tol, flg));
5379   } else {
5380     MatType mattype;
5381 
5382     PetscCall(MatGetType(f ? B : A, &mattype));
5383     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5384   }
5385   PetscFunctionReturn(PETSC_SUCCESS);
5386 }
5387 
5388 /*@
5389   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5390 
5391   Collective
5392 
5393   Input Parameters:
5394 + mat   - the matrix to transpose and complex conjugate
5395 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5396 
5397   Output Parameter:
5398 . B - the Hermitian transpose
5399 
5400   Level: intermediate
5401 
5402 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5403 @*/
5404 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5405 {
5406   PetscFunctionBegin;
5407   PetscCall(MatTranspose(mat, reuse, B));
5408 #if defined(PETSC_USE_COMPLEX)
5409   PetscCall(MatConjugate(*B));
5410 #endif
5411   PetscFunctionReturn(PETSC_SUCCESS);
5412 }
5413 
5414 /*@
5415   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5416 
5417   Collective
5418 
5419   Input Parameters:
5420 + A   - the matrix to test
5421 . B   - the matrix to test against, this can equal the first parameter
5422 - tol - tolerance, differences between entries smaller than this are counted as zero
5423 
5424   Output Parameter:
5425 . flg - the result
5426 
5427   Level: intermediate
5428 
5429   Notes:
5430   Only available for `MATAIJ` matrices.
5431 
5432   The sequential algorithm
5433   has a running time of the order of the number of nonzeros; the parallel
5434   test involves parallel copies of the block off-diagonal parts of the matrix.
5435 
5436 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5437 @*/
5438 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5439 {
5440   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5441 
5442   PetscFunctionBegin;
5443   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5444   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5445   PetscAssertPointer(flg, 4);
5446   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5447   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5448   if (f && g) {
5449     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5450     PetscCall((*f)(A, B, tol, flg));
5451   }
5452   PetscFunctionReturn(PETSC_SUCCESS);
5453 }
5454 
5455 /*@
5456   MatPermute - Creates a new matrix with rows and columns permuted from the
5457   original.
5458 
5459   Collective
5460 
5461   Input Parameters:
5462 + mat - the matrix to permute
5463 . row - row permutation, each processor supplies only the permutation for its rows
5464 - col - column permutation, each processor supplies only the permutation for its columns
5465 
5466   Output Parameter:
5467 . B - the permuted matrix
5468 
5469   Level: advanced
5470 
5471   Note:
5472   The index sets map from row/col of permuted matrix to row/col of original matrix.
5473   The index sets should be on the same communicator as mat and have the same local sizes.
5474 
5475   Developer Note:
5476   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5477   exploit the fact that row and col are permutations, consider implementing the
5478   more general `MatCreateSubMatrix()` instead.
5479 
5480 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5481 @*/
5482 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5483 {
5484   PetscFunctionBegin;
5485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5486   PetscValidType(mat, 1);
5487   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5488   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5489   PetscAssertPointer(B, 4);
5490   PetscCheckSameComm(mat, 1, row, 2);
5491   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5492   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5493   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5494   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5495   MatCheckPreallocated(mat, 1);
5496 
5497   if (mat->ops->permute) {
5498     PetscUseTypeMethod(mat, permute, row, col, B);
5499     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5500   } else {
5501     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5502   }
5503   PetscFunctionReturn(PETSC_SUCCESS);
5504 }
5505 
5506 /*@
5507   MatEqual - Compares two matrices.
5508 
5509   Collective
5510 
5511   Input Parameters:
5512 + A - the first matrix
5513 - B - the second matrix
5514 
5515   Output Parameter:
5516 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5517 
5518   Level: intermediate
5519 
5520 .seealso: [](ch_matrices), `Mat`
5521 @*/
5522 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5523 {
5524   PetscFunctionBegin;
5525   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5526   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5527   PetscValidType(A, 1);
5528   PetscValidType(B, 2);
5529   PetscAssertPointer(flg, 3);
5530   PetscCheckSameComm(A, 1, B, 2);
5531   MatCheckPreallocated(A, 1);
5532   MatCheckPreallocated(B, 2);
5533   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5534   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5535   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,
5536              B->cmap->N);
5537   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5538     PetscUseTypeMethod(A, equal, B, flg);
5539   } else {
5540     PetscCall(MatMultEqual(A, B, 10, flg));
5541   }
5542   PetscFunctionReturn(PETSC_SUCCESS);
5543 }
5544 
5545 /*@
5546   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5547   matrices that are stored as vectors.  Either of the two scaling
5548   matrices can be `NULL`.
5549 
5550   Collective
5551 
5552   Input Parameters:
5553 + mat - the matrix to be scaled
5554 . l   - the left scaling vector (or `NULL`)
5555 - r   - the right scaling vector (or `NULL`)
5556 
5557   Level: intermediate
5558 
5559   Note:
5560   `MatDiagonalScale()` computes $A = LAR$, where
5561   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5562   The L scales the rows of the matrix, the R scales the columns of the matrix.
5563 
5564 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5565 @*/
5566 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5567 {
5568   PetscFunctionBegin;
5569   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5570   PetscValidType(mat, 1);
5571   if (l) {
5572     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5573     PetscCheckSameComm(mat, 1, l, 2);
5574   }
5575   if (r) {
5576     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5577     PetscCheckSameComm(mat, 1, r, 3);
5578   }
5579   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5580   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5581   MatCheckPreallocated(mat, 1);
5582   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5583 
5584   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5585   PetscUseTypeMethod(mat, diagonalscale, l, r);
5586   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5587   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5588   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5589   PetscFunctionReturn(PETSC_SUCCESS);
5590 }
5591 
5592 /*@
5593   MatScale - Scales all elements of a matrix by a given number.
5594 
5595   Logically Collective
5596 
5597   Input Parameters:
5598 + mat - the matrix to be scaled
5599 - a   - the scaling value
5600 
5601   Level: intermediate
5602 
5603 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5604 @*/
5605 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5606 {
5607   PetscFunctionBegin;
5608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5609   PetscValidType(mat, 1);
5610   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5611   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5612   PetscValidLogicalCollectiveScalar(mat, a, 2);
5613   MatCheckPreallocated(mat, 1);
5614 
5615   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5616   if (a != (PetscScalar)1.0) {
5617     PetscUseTypeMethod(mat, scale, a);
5618     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5619   }
5620   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5621   PetscFunctionReturn(PETSC_SUCCESS);
5622 }
5623 
5624 /*@
5625   MatNorm - Calculates various norms of a matrix.
5626 
5627   Collective
5628 
5629   Input Parameters:
5630 + mat  - the matrix
5631 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5632 
5633   Output Parameter:
5634 . nrm - the resulting norm
5635 
5636   Level: intermediate
5637 
5638 .seealso: [](ch_matrices), `Mat`
5639 @*/
5640 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5641 {
5642   PetscFunctionBegin;
5643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5644   PetscValidType(mat, 1);
5645   PetscAssertPointer(nrm, 3);
5646 
5647   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5648   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5649   MatCheckPreallocated(mat, 1);
5650 
5651   PetscUseTypeMethod(mat, norm, type, nrm);
5652   PetscFunctionReturn(PETSC_SUCCESS);
5653 }
5654 
5655 /*
5656      This variable is used to prevent counting of MatAssemblyBegin() that
5657    are called from within a MatAssemblyEnd().
5658 */
5659 static PetscInt MatAssemblyEnd_InUse = 0;
5660 /*@
5661   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5662   be called after completing all calls to `MatSetValues()`.
5663 
5664   Collective
5665 
5666   Input Parameters:
5667 + mat  - the matrix
5668 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5669 
5670   Level: beginner
5671 
5672   Notes:
5673   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5674   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5675 
5676   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5677   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5678   using the matrix.
5679 
5680   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5681   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
5682   a global collective operation requiring all processes that share the matrix.
5683 
5684   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5685   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5686   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5687 
5688 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5689 @*/
5690 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5691 {
5692   PetscFunctionBegin;
5693   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5694   PetscValidType(mat, 1);
5695   MatCheckPreallocated(mat, 1);
5696   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5697   if (mat->assembled) {
5698     mat->was_assembled = PETSC_TRUE;
5699     mat->assembled     = PETSC_FALSE;
5700   }
5701 
5702   if (!MatAssemblyEnd_InUse) {
5703     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5704     PetscTryTypeMethod(mat, assemblybegin, type);
5705     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5706   } else PetscTryTypeMethod(mat, assemblybegin, type);
5707   PetscFunctionReturn(PETSC_SUCCESS);
5708 }
5709 
5710 /*@
5711   MatAssembled - Indicates if a matrix has been assembled and is ready for
5712   use; for example, in matrix-vector product.
5713 
5714   Not Collective
5715 
5716   Input Parameter:
5717 . mat - the matrix
5718 
5719   Output Parameter:
5720 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5721 
5722   Level: advanced
5723 
5724 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5725 @*/
5726 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5727 {
5728   PetscFunctionBegin;
5729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5730   PetscAssertPointer(assembled, 2);
5731   *assembled = mat->assembled;
5732   PetscFunctionReturn(PETSC_SUCCESS);
5733 }
5734 
5735 /*@
5736   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5737   be called after `MatAssemblyBegin()`.
5738 
5739   Collective
5740 
5741   Input Parameters:
5742 + mat  - the matrix
5743 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5744 
5745   Options Database Keys:
5746 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5747 . -mat_view ::ascii_info_detail      - Prints more detailed info
5748 . -mat_view                          - Prints matrix in ASCII format
5749 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5750 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5751 . -display <name>                    - Sets display name (default is host)
5752 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5753 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5754 . -viewer_socket_machine <machine>   - Machine to use for socket
5755 . -viewer_socket_port <port>         - Port number to use for socket
5756 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5757 
5758   Level: beginner
5759 
5760 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5761 @*/
5762 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5763 {
5764   static PetscInt inassm = 0;
5765   PetscBool       flg    = PETSC_FALSE;
5766 
5767   PetscFunctionBegin;
5768   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5769   PetscValidType(mat, 1);
5770 
5771   inassm++;
5772   MatAssemblyEnd_InUse++;
5773   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5774     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5775     PetscTryTypeMethod(mat, assemblyend, type);
5776     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5777   } else PetscTryTypeMethod(mat, assemblyend, type);
5778 
5779   /* Flush assembly is not a true assembly */
5780   if (type != MAT_FLUSH_ASSEMBLY) {
5781     if (mat->num_ass) {
5782       if (!mat->symmetry_eternal) {
5783         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5784         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5785       }
5786       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5787       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5788     }
5789     mat->num_ass++;
5790     mat->assembled        = PETSC_TRUE;
5791     mat->ass_nonzerostate = mat->nonzerostate;
5792   }
5793 
5794   mat->insertmode = NOT_SET_VALUES;
5795   MatAssemblyEnd_InUse--;
5796   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5797   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5798     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5799 
5800     if (mat->checksymmetryonassembly) {
5801       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5802       if (flg) {
5803         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5804       } else {
5805         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5806       }
5807     }
5808     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5809   }
5810   inassm--;
5811   PetscFunctionReturn(PETSC_SUCCESS);
5812 }
5813 
5814 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5815 /*@
5816   MatSetOption - Sets a parameter option for a matrix. Some options
5817   may be specific to certain storage formats.  Some options
5818   determine how values will be inserted (or added). Sorted,
5819   row-oriented input will generally assemble the fastest. The default
5820   is row-oriented.
5821 
5822   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5823 
5824   Input Parameters:
5825 + mat - the matrix
5826 . op  - the option, one of those listed below (and possibly others),
5827 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5828 
5829   Options Describing Matrix Structure:
5830 + `MAT_SPD`                         - symmetric positive definite
5831 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5832 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5833 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5834 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5835 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5836 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5837 
5838    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5839    do not need to be computed (usually at a high cost)
5840 
5841    Options For Use with `MatSetValues()`:
5842    Insert a logically dense subblock, which can be
5843 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5844 
5845    These options reflect the data you pass in with `MatSetValues()`; it has
5846    nothing to do with how the data is stored internally in the matrix
5847    data structure.
5848 
5849    When (re)assembling a matrix, we can restrict the input for
5850    efficiency/debugging purposes.  These options include
5851 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5852 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5853 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5854 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5855 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5856 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5857         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5858         performance for very large process counts.
5859 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5860         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5861         functions, instead sending only neighbor messages.
5862 
5863   Level: intermediate
5864 
5865   Notes:
5866   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5867 
5868   Some options are relevant only for particular matrix types and
5869   are thus ignored by others.  Other options are not supported by
5870   certain matrix types and will generate an error message if set.
5871 
5872   If using Fortran to compute a matrix, one may need to
5873   use the column-oriented option (or convert to the row-oriented
5874   format).
5875 
5876   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5877   that would generate a new entry in the nonzero structure is instead
5878   ignored.  Thus, if memory has not already been allocated for this particular
5879   data, then the insertion is ignored. For dense matrices, in which
5880   the entire array is allocated, no entries are ever ignored.
5881   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5882 
5883   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5884   that would generate a new entry in the nonzero structure instead produces
5885   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
5886 
5887   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5888   that would generate a new entry that has not been preallocated will
5889   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5890   only.) This is a useful flag when debugging matrix memory preallocation.
5891   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5892 
5893   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5894   other processors should be dropped, rather than stashed.
5895   This is useful if you know that the "owning" processor is also
5896   always generating the correct matrix entries, so that PETSc need
5897   not transfer duplicate entries generated on another processor.
5898 
5899   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5900   searches during matrix assembly. When this flag is set, the hash table
5901   is created during the first matrix assembly. This hash table is
5902   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5903   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5904   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5905   supported by `MATMPIBAIJ` format only.
5906 
5907   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5908   are kept in the nonzero structure
5909 
5910   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5911   a zero location in the matrix
5912 
5913   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5914 
5915   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5916   zero row routines and thus improves performance for very large process counts.
5917 
5918   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5919   part of the matrix (since they should match the upper triangular part).
5920 
5921   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5922   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5923   with finite difference schemes with non-periodic boundary conditions.
5924 
5925   Developer Note:
5926   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5927   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5928   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5929   not changed.
5930 
5931 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5932 @*/
5933 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5934 {
5935   PetscFunctionBegin;
5936   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5937   if (op > 0) {
5938     PetscValidLogicalCollectiveEnum(mat, op, 2);
5939     PetscValidLogicalCollectiveBool(mat, flg, 3);
5940   }
5941 
5942   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);
5943 
5944   switch (op) {
5945   case MAT_FORCE_DIAGONAL_ENTRIES:
5946     mat->force_diagonals = flg;
5947     PetscFunctionReturn(PETSC_SUCCESS);
5948   case MAT_NO_OFF_PROC_ENTRIES:
5949     mat->nooffprocentries = flg;
5950     PetscFunctionReturn(PETSC_SUCCESS);
5951   case MAT_SUBSET_OFF_PROC_ENTRIES:
5952     mat->assembly_subset = flg;
5953     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5954 #if !defined(PETSC_HAVE_MPIUNI)
5955       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5956 #endif
5957       mat->stash.first_assembly_done = PETSC_FALSE;
5958     }
5959     PetscFunctionReturn(PETSC_SUCCESS);
5960   case MAT_NO_OFF_PROC_ZERO_ROWS:
5961     mat->nooffproczerorows = flg;
5962     PetscFunctionReturn(PETSC_SUCCESS);
5963   case MAT_SPD:
5964     if (flg) {
5965       mat->spd                    = PETSC_BOOL3_TRUE;
5966       mat->symmetric              = PETSC_BOOL3_TRUE;
5967       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5968     } else {
5969       mat->spd = PETSC_BOOL3_FALSE;
5970     }
5971     break;
5972   case MAT_SYMMETRIC:
5973     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5974     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5975 #if !defined(PETSC_USE_COMPLEX)
5976     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5977 #endif
5978     break;
5979   case MAT_HERMITIAN:
5980     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5981     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5982 #if !defined(PETSC_USE_COMPLEX)
5983     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5984 #endif
5985     break;
5986   case MAT_STRUCTURALLY_SYMMETRIC:
5987     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5988     break;
5989   case MAT_SYMMETRY_ETERNAL:
5990     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");
5991     mat->symmetry_eternal = flg;
5992     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5993     break;
5994   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5995     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");
5996     mat->structural_symmetry_eternal = flg;
5997     break;
5998   case MAT_SPD_ETERNAL:
5999     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");
6000     mat->spd_eternal = flg;
6001     if (flg) {
6002       mat->structural_symmetry_eternal = PETSC_TRUE;
6003       mat->symmetry_eternal            = PETSC_TRUE;
6004     }
6005     break;
6006   case MAT_STRUCTURE_ONLY:
6007     mat->structure_only = flg;
6008     break;
6009   case MAT_SORTED_FULL:
6010     mat->sortedfull = flg;
6011     break;
6012   default:
6013     break;
6014   }
6015   PetscTryTypeMethod(mat, setoption, op, flg);
6016   PetscFunctionReturn(PETSC_SUCCESS);
6017 }
6018 
6019 /*@
6020   MatGetOption - Gets a parameter option that has been set for a matrix.
6021 
6022   Logically Collective
6023 
6024   Input Parameters:
6025 + mat - the matrix
6026 - op  - the option, this only responds to certain options, check the code for which ones
6027 
6028   Output Parameter:
6029 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6030 
6031   Level: intermediate
6032 
6033   Notes:
6034   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6035 
6036   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6037   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6038 
6039 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6040     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6041 @*/
6042 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6043 {
6044   PetscFunctionBegin;
6045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6046   PetscValidType(mat, 1);
6047 
6048   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);
6049   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()");
6050 
6051   switch (op) {
6052   case MAT_NO_OFF_PROC_ENTRIES:
6053     *flg = mat->nooffprocentries;
6054     break;
6055   case MAT_NO_OFF_PROC_ZERO_ROWS:
6056     *flg = mat->nooffproczerorows;
6057     break;
6058   case MAT_SYMMETRIC:
6059     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6060     break;
6061   case MAT_HERMITIAN:
6062     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6063     break;
6064   case MAT_STRUCTURALLY_SYMMETRIC:
6065     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6066     break;
6067   case MAT_SPD:
6068     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6069     break;
6070   case MAT_SYMMETRY_ETERNAL:
6071     *flg = mat->symmetry_eternal;
6072     break;
6073   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6074     *flg = mat->symmetry_eternal;
6075     break;
6076   default:
6077     break;
6078   }
6079   PetscFunctionReturn(PETSC_SUCCESS);
6080 }
6081 
6082 /*@
6083   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6084   this routine retains the old nonzero structure.
6085 
6086   Logically Collective
6087 
6088   Input Parameter:
6089 . mat - the matrix
6090 
6091   Level: intermediate
6092 
6093   Note:
6094   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.
6095   See the Performance chapter of the users manual for information on preallocating matrices.
6096 
6097 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6098 @*/
6099 PetscErrorCode MatZeroEntries(Mat mat)
6100 {
6101   PetscFunctionBegin;
6102   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6103   PetscValidType(mat, 1);
6104   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6105   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");
6106   MatCheckPreallocated(mat, 1);
6107 
6108   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6109   PetscUseTypeMethod(mat, zeroentries);
6110   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6111   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6112   PetscFunctionReturn(PETSC_SUCCESS);
6113 }
6114 
6115 /*@
6116   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6117   of a set of rows and columns of a matrix.
6118 
6119   Collective
6120 
6121   Input Parameters:
6122 + mat     - the matrix
6123 . numRows - the number of rows/columns to zero
6124 . rows    - the global row indices
6125 . diag    - value put in the diagonal of the eliminated rows
6126 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6127 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6128 
6129   Level: intermediate
6130 
6131   Notes:
6132   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6133 
6134   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6135   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
6136 
6137   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6138   Krylov method to take advantage of the known solution on the zeroed rows.
6139 
6140   For the parallel case, all processes that share the matrix (i.e.,
6141   those in the communicator used for matrix creation) MUST call this
6142   routine, regardless of whether any rows being zeroed are owned by
6143   them.
6144 
6145   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6146 
6147   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6148   list only rows local to itself).
6149 
6150   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6151 
6152 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6153           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6154 @*/
6155 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6156 {
6157   PetscFunctionBegin;
6158   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6159   PetscValidType(mat, 1);
6160   if (numRows) PetscAssertPointer(rows, 3);
6161   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6162   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6163   MatCheckPreallocated(mat, 1);
6164 
6165   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6166   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6167   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6168   PetscFunctionReturn(PETSC_SUCCESS);
6169 }
6170 
6171 /*@
6172   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6173   of a set of rows and columns of a matrix.
6174 
6175   Collective
6176 
6177   Input Parameters:
6178 + mat  - the matrix
6179 . is   - the rows to zero
6180 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6181 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6182 - b    - optional vector of right hand side, that will be adjusted by provided solution
6183 
6184   Level: intermediate
6185 
6186   Note:
6187   See `MatZeroRowsColumns()` for details on how this routine operates.
6188 
6189 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6190           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6191 @*/
6192 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6193 {
6194   PetscInt        numRows;
6195   const PetscInt *rows;
6196 
6197   PetscFunctionBegin;
6198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6199   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6200   PetscValidType(mat, 1);
6201   PetscValidType(is, 2);
6202   PetscCall(ISGetLocalSize(is, &numRows));
6203   PetscCall(ISGetIndices(is, &rows));
6204   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6205   PetscCall(ISRestoreIndices(is, &rows));
6206   PetscFunctionReturn(PETSC_SUCCESS);
6207 }
6208 
6209 /*@
6210   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6211   of a set of rows of a matrix.
6212 
6213   Collective
6214 
6215   Input Parameters:
6216 + mat     - the matrix
6217 . numRows - the number of rows to zero
6218 . rows    - the global row indices
6219 . diag    - value put in the diagonal of the zeroed rows
6220 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6221 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6222 
6223   Level: intermediate
6224 
6225   Notes:
6226   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6227 
6228   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6229 
6230   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6231   Krylov method to take advantage of the known solution on the zeroed rows.
6232 
6233   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)
6234   from the matrix.
6235 
6236   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6237   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
6238   formats this does not alter the nonzero structure.
6239 
6240   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6241   of the matrix is not changed the values are
6242   merely zeroed.
6243 
6244   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6245   formats can optionally remove the main diagonal entry from the
6246   nonzero structure as well, by passing 0.0 as the final argument).
6247 
6248   For the parallel case, all processes that share the matrix (i.e.,
6249   those in the communicator used for matrix creation) MUST call this
6250   routine, regardless of whether any rows being zeroed are owned by
6251   them.
6252 
6253   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6254   list only rows local to itself).
6255 
6256   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6257   owns that are to be zeroed. This saves a global synchronization in the implementation.
6258 
6259 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6260           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6261 @*/
6262 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6263 {
6264   PetscFunctionBegin;
6265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6266   PetscValidType(mat, 1);
6267   if (numRows) PetscAssertPointer(rows, 3);
6268   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6269   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6270   MatCheckPreallocated(mat, 1);
6271 
6272   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6273   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6274   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6275   PetscFunctionReturn(PETSC_SUCCESS);
6276 }
6277 
6278 /*@
6279   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6280   of a set of rows of a matrix.
6281 
6282   Collective
6283 
6284   Input Parameters:
6285 + mat  - the matrix
6286 . is   - index set of rows to remove (if `NULL` then no row is removed)
6287 . diag - value put in all diagonals of eliminated rows
6288 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6289 - b    - optional vector of right hand side, that will be adjusted by provided solution
6290 
6291   Level: intermediate
6292 
6293   Note:
6294   See `MatZeroRows()` for details on how this routine operates.
6295 
6296 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6297           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6298 @*/
6299 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6300 {
6301   PetscInt        numRows = 0;
6302   const PetscInt *rows    = NULL;
6303 
6304   PetscFunctionBegin;
6305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6306   PetscValidType(mat, 1);
6307   if (is) {
6308     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6309     PetscCall(ISGetLocalSize(is, &numRows));
6310     PetscCall(ISGetIndices(is, &rows));
6311   }
6312   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6313   if (is) PetscCall(ISRestoreIndices(is, &rows));
6314   PetscFunctionReturn(PETSC_SUCCESS);
6315 }
6316 
6317 /*@
6318   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6319   of a set of rows of a matrix. These rows must be local to the process.
6320 
6321   Collective
6322 
6323   Input Parameters:
6324 + mat     - the matrix
6325 . numRows - the number of rows to remove
6326 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6327 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6328 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6329 - b       - optional vector of right hand side, that will be adjusted by provided solution
6330 
6331   Level: intermediate
6332 
6333   Notes:
6334   See `MatZeroRows()` for details on how this routine operates.
6335 
6336   The grid coordinates are across the entire grid, not just the local portion
6337 
6338   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6339   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6340   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6341   `DM_BOUNDARY_PERIODIC` boundary type.
6342 
6343   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
6344   a single value per point) you can skip filling those indices.
6345 
6346   Fortran Note:
6347   `idxm` and `idxn` should be declared as
6348 $     MatStencil idxm(4, m)
6349   and the values inserted using
6350 .vb
6351     idxm(MatStencil_i, 1) = i
6352     idxm(MatStencil_j, 1) = j
6353     idxm(MatStencil_k, 1) = k
6354     idxm(MatStencil_c, 1) = c
6355    etc
6356 .ve
6357 
6358 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6359           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6360 @*/
6361 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6362 {
6363   PetscInt  dim    = mat->stencil.dim;
6364   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6365   PetscInt *dims   = mat->stencil.dims + 1;
6366   PetscInt *starts = mat->stencil.starts;
6367   PetscInt *dxm    = (PetscInt *)rows;
6368   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6369 
6370   PetscFunctionBegin;
6371   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6372   PetscValidType(mat, 1);
6373   if (numRows) PetscAssertPointer(rows, 3);
6374 
6375   PetscCall(PetscMalloc1(numRows, &jdxm));
6376   for (i = 0; i < numRows; ++i) {
6377     /* Skip unused dimensions (they are ordered k, j, i, c) */
6378     for (j = 0; j < 3 - sdim; ++j) dxm++;
6379     /* Local index in X dir */
6380     tmp = *dxm++ - starts[0];
6381     /* Loop over remaining dimensions */
6382     for (j = 0; j < dim - 1; ++j) {
6383       /* If nonlocal, set index to be negative */
6384       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6385       /* Update local index */
6386       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6387     }
6388     /* Skip component slot if necessary */
6389     if (mat->stencil.noc) dxm++;
6390     /* Local row number */
6391     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6392   }
6393   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6394   PetscCall(PetscFree(jdxm));
6395   PetscFunctionReturn(PETSC_SUCCESS);
6396 }
6397 
6398 /*@
6399   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6400   of a set of rows and columns of a matrix.
6401 
6402   Collective
6403 
6404   Input Parameters:
6405 + mat     - the matrix
6406 . numRows - the number of rows/columns to remove
6407 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6408 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6409 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6410 - b       - optional vector of right hand side, that will be adjusted by provided solution
6411 
6412   Level: intermediate
6413 
6414   Notes:
6415   See `MatZeroRowsColumns()` for details on how this routine operates.
6416 
6417   The grid coordinates are across the entire grid, not just the local portion
6418 
6419   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6420   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6421   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6422   `DM_BOUNDARY_PERIODIC` boundary type.
6423 
6424   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
6425   a single value per point) you can skip filling those indices.
6426 
6427   Fortran Note:
6428   `idxm` and `idxn` should be declared as
6429 $     MatStencil idxm(4, m)
6430   and the values inserted using
6431 .vb
6432     idxm(MatStencil_i, 1) = i
6433     idxm(MatStencil_j, 1) = j
6434     idxm(MatStencil_k, 1) = k
6435     idxm(MatStencil_c, 1) = c
6436     etc
6437 .ve
6438 
6439 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6440           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6441 @*/
6442 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6443 {
6444   PetscInt  dim    = mat->stencil.dim;
6445   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6446   PetscInt *dims   = mat->stencil.dims + 1;
6447   PetscInt *starts = mat->stencil.starts;
6448   PetscInt *dxm    = (PetscInt *)rows;
6449   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6450 
6451   PetscFunctionBegin;
6452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6453   PetscValidType(mat, 1);
6454   if (numRows) PetscAssertPointer(rows, 3);
6455 
6456   PetscCall(PetscMalloc1(numRows, &jdxm));
6457   for (i = 0; i < numRows; ++i) {
6458     /* Skip unused dimensions (they are ordered k, j, i, c) */
6459     for (j = 0; j < 3 - sdim; ++j) dxm++;
6460     /* Local index in X dir */
6461     tmp = *dxm++ - starts[0];
6462     /* Loop over remaining dimensions */
6463     for (j = 0; j < dim - 1; ++j) {
6464       /* If nonlocal, set index to be negative */
6465       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6466       /* Update local index */
6467       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6468     }
6469     /* Skip component slot if necessary */
6470     if (mat->stencil.noc) dxm++;
6471     /* Local row number */
6472     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6473   }
6474   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6475   PetscCall(PetscFree(jdxm));
6476   PetscFunctionReturn(PETSC_SUCCESS);
6477 }
6478 
6479 /*@C
6480   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6481   of a set of rows of a matrix; using local numbering of rows.
6482 
6483   Collective
6484 
6485   Input Parameters:
6486 + mat     - the matrix
6487 . numRows - the number of rows to remove
6488 . rows    - the local row indices
6489 . diag    - value put in all diagonals of eliminated rows
6490 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6491 - b       - optional vector of right hand side, that will be adjusted by provided solution
6492 
6493   Level: intermediate
6494 
6495   Notes:
6496   Before calling `MatZeroRowsLocal()`, the user must first set the
6497   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6498 
6499   See `MatZeroRows()` for details on how this routine operates.
6500 
6501 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6502           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6503 @*/
6504 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6505 {
6506   PetscFunctionBegin;
6507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6508   PetscValidType(mat, 1);
6509   if (numRows) PetscAssertPointer(rows, 3);
6510   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6511   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6512   MatCheckPreallocated(mat, 1);
6513 
6514   if (mat->ops->zerorowslocal) {
6515     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6516   } else {
6517     IS              is, newis;
6518     const PetscInt *newRows;
6519 
6520     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6521     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6522     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6523     PetscCall(ISGetIndices(newis, &newRows));
6524     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6525     PetscCall(ISRestoreIndices(newis, &newRows));
6526     PetscCall(ISDestroy(&newis));
6527     PetscCall(ISDestroy(&is));
6528   }
6529   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6530   PetscFunctionReturn(PETSC_SUCCESS);
6531 }
6532 
6533 /*@
6534   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6535   of a set of rows of a matrix; using local numbering of rows.
6536 
6537   Collective
6538 
6539   Input Parameters:
6540 + mat  - the matrix
6541 . is   - index set of rows to remove
6542 . diag - value put in all diagonals of eliminated rows
6543 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6544 - b    - optional vector of right hand side, that will be adjusted by provided solution
6545 
6546   Level: intermediate
6547 
6548   Notes:
6549   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6550   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6551 
6552   See `MatZeroRows()` for details on how this routine operates.
6553 
6554 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6555           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6556 @*/
6557 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6558 {
6559   PetscInt        numRows;
6560   const PetscInt *rows;
6561 
6562   PetscFunctionBegin;
6563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6564   PetscValidType(mat, 1);
6565   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6566   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6567   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6568   MatCheckPreallocated(mat, 1);
6569 
6570   PetscCall(ISGetLocalSize(is, &numRows));
6571   PetscCall(ISGetIndices(is, &rows));
6572   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6573   PetscCall(ISRestoreIndices(is, &rows));
6574   PetscFunctionReturn(PETSC_SUCCESS);
6575 }
6576 
6577 /*@
6578   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6579   of a set of rows and columns of a matrix; using local numbering of rows.
6580 
6581   Collective
6582 
6583   Input Parameters:
6584 + mat     - the matrix
6585 . numRows - the number of rows to remove
6586 . rows    - the global row indices
6587 . diag    - value put in all diagonals of eliminated rows
6588 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6589 - b       - optional vector of right hand side, that will be adjusted by provided solution
6590 
6591   Level: intermediate
6592 
6593   Notes:
6594   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6595   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6596 
6597   See `MatZeroRowsColumns()` for details on how this routine operates.
6598 
6599 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6600           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6601 @*/
6602 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6603 {
6604   IS              is, newis;
6605   const PetscInt *newRows;
6606 
6607   PetscFunctionBegin;
6608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6609   PetscValidType(mat, 1);
6610   if (numRows) PetscAssertPointer(rows, 3);
6611   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6612   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6613   MatCheckPreallocated(mat, 1);
6614 
6615   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6616   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6617   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6618   PetscCall(ISGetIndices(newis, &newRows));
6619   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6620   PetscCall(ISRestoreIndices(newis, &newRows));
6621   PetscCall(ISDestroy(&newis));
6622   PetscCall(ISDestroy(&is));
6623   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6624   PetscFunctionReturn(PETSC_SUCCESS);
6625 }
6626 
6627 /*@
6628   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6629   of a set of rows and columns of a matrix; using local numbering of rows.
6630 
6631   Collective
6632 
6633   Input Parameters:
6634 + mat  - the matrix
6635 . is   - index set of rows to remove
6636 . diag - value put in all diagonals of eliminated rows
6637 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6638 - b    - optional vector of right hand side, that will be adjusted by provided solution
6639 
6640   Level: intermediate
6641 
6642   Notes:
6643   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6644   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6645 
6646   See `MatZeroRowsColumns()` for details on how this routine operates.
6647 
6648 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6649           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6650 @*/
6651 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6652 {
6653   PetscInt        numRows;
6654   const PetscInt *rows;
6655 
6656   PetscFunctionBegin;
6657   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6658   PetscValidType(mat, 1);
6659   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6660   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6661   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6662   MatCheckPreallocated(mat, 1);
6663 
6664   PetscCall(ISGetLocalSize(is, &numRows));
6665   PetscCall(ISGetIndices(is, &rows));
6666   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6667   PetscCall(ISRestoreIndices(is, &rows));
6668   PetscFunctionReturn(PETSC_SUCCESS);
6669 }
6670 
6671 /*@C
6672   MatGetSize - Returns the numbers of rows and columns in a matrix.
6673 
6674   Not Collective
6675 
6676   Input Parameter:
6677 . mat - the matrix
6678 
6679   Output Parameters:
6680 + m - the number of global rows
6681 - n - the number of global columns
6682 
6683   Level: beginner
6684 
6685   Note:
6686   Both output parameters can be `NULL` on input.
6687 
6688 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6689 @*/
6690 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6691 {
6692   PetscFunctionBegin;
6693   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6694   if (m) *m = mat->rmap->N;
6695   if (n) *n = mat->cmap->N;
6696   PetscFunctionReturn(PETSC_SUCCESS);
6697 }
6698 
6699 /*@C
6700   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6701   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6702 
6703   Not Collective
6704 
6705   Input Parameter:
6706 . mat - the matrix
6707 
6708   Output Parameters:
6709 + m - the number of local rows, use `NULL` to not obtain this value
6710 - n - the number of local columns, use `NULL` to not obtain this value
6711 
6712   Level: beginner
6713 
6714 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6715 @*/
6716 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6717 {
6718   PetscFunctionBegin;
6719   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6720   if (m) PetscAssertPointer(m, 2);
6721   if (n) PetscAssertPointer(n, 3);
6722   if (m) *m = mat->rmap->n;
6723   if (n) *n = mat->cmap->n;
6724   PetscFunctionReturn(PETSC_SUCCESS);
6725 }
6726 
6727 /*@C
6728   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6729   vector one multiplies this matrix by that are owned by this processor.
6730 
6731   Not Collective, unless matrix has not been allocated, then collective
6732 
6733   Input Parameter:
6734 . mat - the matrix
6735 
6736   Output Parameters:
6737 + m - the global index of the first local column, use `NULL` to not obtain this value
6738 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6739 
6740   Level: developer
6741 
6742   Note:
6743   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6744   Layouts](sec_matlayout) for details on matrix layouts.
6745 
6746 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6747 @*/
6748 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6749 {
6750   PetscFunctionBegin;
6751   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6752   PetscValidType(mat, 1);
6753   if (m) PetscAssertPointer(m, 2);
6754   if (n) PetscAssertPointer(n, 3);
6755   MatCheckPreallocated(mat, 1);
6756   if (m) *m = mat->cmap->rstart;
6757   if (n) *n = mat->cmap->rend;
6758   PetscFunctionReturn(PETSC_SUCCESS);
6759 }
6760 
6761 /*@C
6762   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6763   this MPI process.
6764 
6765   Not Collective
6766 
6767   Input Parameter:
6768 . mat - the matrix
6769 
6770   Output Parameters:
6771 + m - the global index of the first local row, use `NULL` to not obtain this value
6772 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6773 
6774   Level: beginner
6775 
6776   Note:
6777   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6778   would contain the result of a matrix vector product with this matrix. See [Matrix
6779   Layouts](sec_matlayout) for details on matrix layouts.
6780 
6781 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6782           `PetscLayout`
6783 @*/
6784 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6785 {
6786   PetscFunctionBegin;
6787   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6788   PetscValidType(mat, 1);
6789   if (m) PetscAssertPointer(m, 2);
6790   if (n) PetscAssertPointer(n, 3);
6791   MatCheckPreallocated(mat, 1);
6792   if (m) *m = mat->rmap->rstart;
6793   if (n) *n = mat->rmap->rend;
6794   PetscFunctionReturn(PETSC_SUCCESS);
6795 }
6796 
6797 /*@C
6798   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6799   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6800 
6801   Not Collective, unless matrix has not been allocated
6802 
6803   Input Parameter:
6804 . mat - the matrix
6805 
6806   Output Parameter:
6807 . ranges - start of each processors portion plus one more than the total length at the end
6808 
6809   Level: beginner
6810 
6811   Note:
6812   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6813   would contain the result of a matrix vector product with this matrix. See [Matrix
6814   Layouts](sec_matlayout) for details on matrix layouts.
6815 
6816 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6817 @*/
6818 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6819 {
6820   PetscFunctionBegin;
6821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6822   PetscValidType(mat, 1);
6823   MatCheckPreallocated(mat, 1);
6824   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6825   PetscFunctionReturn(PETSC_SUCCESS);
6826 }
6827 
6828 /*@C
6829   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6830   vector one multiplies this vector by that are owned by each processor.
6831 
6832   Not Collective, unless matrix has not been allocated
6833 
6834   Input Parameter:
6835 . mat - the matrix
6836 
6837   Output Parameter:
6838 . ranges - start of each processors portion plus one more than the total length at the end
6839 
6840   Level: beginner
6841 
6842   Note:
6843   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6844   Layouts](sec_matlayout) for details on matrix layouts.
6845 
6846 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6847 @*/
6848 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6849 {
6850   PetscFunctionBegin;
6851   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6852   PetscValidType(mat, 1);
6853   MatCheckPreallocated(mat, 1);
6854   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6855   PetscFunctionReturn(PETSC_SUCCESS);
6856 }
6857 
6858 /*@C
6859   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6860 
6861   Not Collective
6862 
6863   Input Parameter:
6864 . A - matrix
6865 
6866   Output Parameters:
6867 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6868 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6869 
6870   Level: intermediate
6871 
6872   Note:
6873   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6874   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6875   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6876   details on matrix layouts.
6877 
6878 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6879 @*/
6880 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6881 {
6882   PetscErrorCode (*f)(Mat, IS *, IS *);
6883 
6884   PetscFunctionBegin;
6885   MatCheckPreallocated(A, 1);
6886   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6887   if (f) {
6888     PetscCall((*f)(A, rows, cols));
6889   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6890     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6891     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6892   }
6893   PetscFunctionReturn(PETSC_SUCCESS);
6894 }
6895 
6896 /*@C
6897   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6898   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6899   to complete the factorization.
6900 
6901   Collective
6902 
6903   Input Parameters:
6904 + fact - the factorized matrix obtained with `MatGetFactor()`
6905 . mat  - the matrix
6906 . row  - row permutation
6907 . col  - column permutation
6908 - info - structure containing
6909 .vb
6910       levels - number of levels of fill.
6911       expected fill - as ratio of original fill.
6912       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6913                 missing diagonal entries)
6914 .ve
6915 
6916   Level: developer
6917 
6918   Notes:
6919   See [Matrix Factorization](sec_matfactor) for additional information.
6920 
6921   Most users should employ the `KSP` interface for linear solvers
6922   instead of working directly with matrix algebra routines such as this.
6923   See, e.g., `KSPCreate()`.
6924 
6925   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
6926 
6927   Developer Note:
6928   The Fortran interface is not autogenerated as the
6929   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6930 
6931 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6932           `MatGetOrdering()`, `MatFactorInfo`
6933 @*/
6934 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6935 {
6936   PetscFunctionBegin;
6937   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6938   PetscValidType(mat, 2);
6939   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6940   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6941   PetscAssertPointer(info, 5);
6942   PetscAssertPointer(fact, 1);
6943   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6944   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6945   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6946   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6947   MatCheckPreallocated(mat, 2);
6948 
6949   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6950   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6951   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6952   PetscFunctionReturn(PETSC_SUCCESS);
6953 }
6954 
6955 /*@C
6956   MatICCFactorSymbolic - Performs symbolic incomplete
6957   Cholesky factorization for a symmetric matrix.  Use
6958   `MatCholeskyFactorNumeric()` to complete the factorization.
6959 
6960   Collective
6961 
6962   Input Parameters:
6963 + fact - the factorized matrix obtained with `MatGetFactor()`
6964 . mat  - the matrix to be factored
6965 . perm - row and column permutation
6966 - info - structure containing
6967 .vb
6968       levels - number of levels of fill.
6969       expected fill - as ratio of original fill.
6970 .ve
6971 
6972   Level: developer
6973 
6974   Notes:
6975   Most users should employ the `KSP` interface for linear solvers
6976   instead of working directly with matrix algebra routines such as this.
6977   See, e.g., `KSPCreate()`.
6978 
6979   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
6980 
6981   Developer Note:
6982   The Fortran interface is not autogenerated as the
6983   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6984 
6985 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6986 @*/
6987 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6988 {
6989   PetscFunctionBegin;
6990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6991   PetscValidType(mat, 2);
6992   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6993   PetscAssertPointer(info, 4);
6994   PetscAssertPointer(fact, 1);
6995   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6996   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6997   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6998   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6999   MatCheckPreallocated(mat, 2);
7000 
7001   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7002   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7003   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7004   PetscFunctionReturn(PETSC_SUCCESS);
7005 }
7006 
7007 /*@C
7008   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7009   points to an array of valid matrices, they may be reused to store the new
7010   submatrices.
7011 
7012   Collective
7013 
7014   Input Parameters:
7015 + mat   - the matrix
7016 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7017 . irow  - index set of rows to extract
7018 . icol  - index set of columns to extract
7019 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7020 
7021   Output Parameter:
7022 . submat - the array of submatrices
7023 
7024   Level: advanced
7025 
7026   Notes:
7027   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7028   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7029   to extract a parallel submatrix.
7030 
7031   Some matrix types place restrictions on the row and column
7032   indices, such as that they be sorted or that they be equal to each other.
7033 
7034   The index sets may not have duplicate entries.
7035 
7036   When extracting submatrices from a parallel matrix, each processor can
7037   form a different submatrix by setting the rows and columns of its
7038   individual index sets according to the local submatrix desired.
7039 
7040   When finished using the submatrices, the user should destroy
7041   them with `MatDestroySubMatrices()`.
7042 
7043   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7044   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7045 
7046   This routine creates the matrices in submat; you should NOT create them before
7047   calling it. It also allocates the array of matrix pointers submat.
7048 
7049   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7050   request one row/column in a block, they must request all rows/columns that are in
7051   that block. For example, if the block size is 2 you cannot request just row 0 and
7052   column 0.
7053 
7054   Fortran Note:
7055   The Fortran interface is slightly different from that given below; it
7056   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7057 
7058 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7059 @*/
7060 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7061 {
7062   PetscInt  i;
7063   PetscBool eq;
7064 
7065   PetscFunctionBegin;
7066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7067   PetscValidType(mat, 1);
7068   if (n) {
7069     PetscAssertPointer(irow, 3);
7070     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7071     PetscAssertPointer(icol, 4);
7072     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7073   }
7074   PetscAssertPointer(submat, 6);
7075   if (n && scall == MAT_REUSE_MATRIX) {
7076     PetscAssertPointer(*submat, 6);
7077     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7078   }
7079   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7080   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7081   MatCheckPreallocated(mat, 1);
7082   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7083   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7084   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7085   for (i = 0; i < n; i++) {
7086     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7087     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7088     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7089 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7090     if (mat->boundtocpu && mat->bindingpropagates) {
7091       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7092       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7093     }
7094 #endif
7095   }
7096   PetscFunctionReturn(PETSC_SUCCESS);
7097 }
7098 
7099 /*@C
7100   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7101 
7102   Collective
7103 
7104   Input Parameters:
7105 + mat   - the matrix
7106 . n     - the number of submatrixes to be extracted
7107 . irow  - index set of rows to extract
7108 . icol  - index set of columns to extract
7109 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7110 
7111   Output Parameter:
7112 . submat - the array of submatrices
7113 
7114   Level: advanced
7115 
7116   Note:
7117   This is used by `PCGASM`
7118 
7119 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7120 @*/
7121 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7122 {
7123   PetscInt  i;
7124   PetscBool eq;
7125 
7126   PetscFunctionBegin;
7127   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7128   PetscValidType(mat, 1);
7129   if (n) {
7130     PetscAssertPointer(irow, 3);
7131     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7132     PetscAssertPointer(icol, 4);
7133     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7134   }
7135   PetscAssertPointer(submat, 6);
7136   if (n && scall == MAT_REUSE_MATRIX) {
7137     PetscAssertPointer(*submat, 6);
7138     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7139   }
7140   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7141   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7142   MatCheckPreallocated(mat, 1);
7143 
7144   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7145   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7146   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7147   for (i = 0; i < n; i++) {
7148     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7149     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7150   }
7151   PetscFunctionReturn(PETSC_SUCCESS);
7152 }
7153 
7154 /*@C
7155   MatDestroyMatrices - Destroys an array of matrices.
7156 
7157   Collective
7158 
7159   Input Parameters:
7160 + n   - the number of local matrices
7161 - mat - the matrices (this is a pointer to the array of matrices)
7162 
7163   Level: advanced
7164 
7165   Note:
7166   Frees not only the matrices, but also the array that contains the matrices
7167 
7168   Fortran Note:
7169   This does not free the array.
7170 
7171 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7172 @*/
7173 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7174 {
7175   PetscInt i;
7176 
7177   PetscFunctionBegin;
7178   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7179   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7180   PetscAssertPointer(mat, 2);
7181 
7182   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7183 
7184   /* memory is allocated even if n = 0 */
7185   PetscCall(PetscFree(*mat));
7186   PetscFunctionReturn(PETSC_SUCCESS);
7187 }
7188 
7189 /*@C
7190   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7191 
7192   Collective
7193 
7194   Input Parameters:
7195 + n   - the number of local matrices
7196 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7197                        sequence of `MatCreateSubMatrices()`)
7198 
7199   Level: advanced
7200 
7201   Note:
7202   Frees not only the matrices, but also the array that contains the matrices
7203 
7204   Fortran Note:
7205   This does not free the array.
7206 
7207 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7208 @*/
7209 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7210 {
7211   Mat mat0;
7212 
7213   PetscFunctionBegin;
7214   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7215   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7216   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7217   PetscAssertPointer(mat, 2);
7218 
7219   mat0 = (*mat)[0];
7220   if (mat0 && mat0->ops->destroysubmatrices) {
7221     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7222   } else {
7223     PetscCall(MatDestroyMatrices(n, mat));
7224   }
7225   PetscFunctionReturn(PETSC_SUCCESS);
7226 }
7227 
7228 /*@C
7229   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7230 
7231   Collective
7232 
7233   Input Parameter:
7234 . mat - the matrix
7235 
7236   Output Parameter:
7237 . matstruct - the sequential matrix with the nonzero structure of mat
7238 
7239   Level: developer
7240 
7241 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7242 @*/
7243 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7244 {
7245   PetscFunctionBegin;
7246   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7247   PetscAssertPointer(matstruct, 2);
7248 
7249   PetscValidType(mat, 1);
7250   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7251   MatCheckPreallocated(mat, 1);
7252 
7253   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7254   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7255   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7256   PetscFunctionReturn(PETSC_SUCCESS);
7257 }
7258 
7259 /*@C
7260   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7261 
7262   Collective
7263 
7264   Input Parameter:
7265 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7266                        sequence of `MatGetSeqNonzeroStructure()`)
7267 
7268   Level: advanced
7269 
7270   Note:
7271   Frees not only the matrices, but also the array that contains the matrices
7272 
7273 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7274 @*/
7275 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7276 {
7277   PetscFunctionBegin;
7278   PetscAssertPointer(mat, 1);
7279   PetscCall(MatDestroy(mat));
7280   PetscFunctionReturn(PETSC_SUCCESS);
7281 }
7282 
7283 /*@
7284   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7285   replaces the index sets by larger ones that represent submatrices with
7286   additional overlap.
7287 
7288   Collective
7289 
7290   Input Parameters:
7291 + mat - the matrix
7292 . n   - the number of index sets
7293 . is  - the array of index sets (these index sets will changed during the call)
7294 - ov  - the additional overlap requested
7295 
7296   Options Database Key:
7297 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7298 
7299   Level: developer
7300 
7301   Note:
7302   The computed overlap preserves the matrix block sizes when the blocks are square.
7303   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7304   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7305 
7306 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7307 @*/
7308 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7309 {
7310   PetscInt i, bs, cbs;
7311 
7312   PetscFunctionBegin;
7313   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7314   PetscValidType(mat, 1);
7315   PetscValidLogicalCollectiveInt(mat, n, 2);
7316   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7317   if (n) {
7318     PetscAssertPointer(is, 3);
7319     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7320   }
7321   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7322   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7323   MatCheckPreallocated(mat, 1);
7324 
7325   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7326   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7327   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7328   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7329   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7330   if (bs == cbs) {
7331     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7332   }
7333   PetscFunctionReturn(PETSC_SUCCESS);
7334 }
7335 
7336 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7337 
7338 /*@
7339   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7340   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7341   additional overlap.
7342 
7343   Collective
7344 
7345   Input Parameters:
7346 + mat - the matrix
7347 . n   - the number of index sets
7348 . is  - the array of index sets (these index sets will changed during the call)
7349 - ov  - the additional overlap requested
7350 
7351   `   Options Database Key:
7352 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7353 
7354   Level: developer
7355 
7356 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7357 @*/
7358 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7359 {
7360   PetscInt i;
7361 
7362   PetscFunctionBegin;
7363   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7364   PetscValidType(mat, 1);
7365   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7366   if (n) {
7367     PetscAssertPointer(is, 3);
7368     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7369   }
7370   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7371   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7372   MatCheckPreallocated(mat, 1);
7373   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7374   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7375   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7376   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7377   PetscFunctionReturn(PETSC_SUCCESS);
7378 }
7379 
7380 /*@
7381   MatGetBlockSize - Returns the matrix block size.
7382 
7383   Not Collective
7384 
7385   Input Parameter:
7386 . mat - the matrix
7387 
7388   Output Parameter:
7389 . bs - block size
7390 
7391   Level: intermediate
7392 
7393   Notes:
7394   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7395 
7396   If the block size has not been set yet this routine returns 1.
7397 
7398 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7399 @*/
7400 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7401 {
7402   PetscFunctionBegin;
7403   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7404   PetscAssertPointer(bs, 2);
7405   *bs = PetscAbs(mat->rmap->bs);
7406   PetscFunctionReturn(PETSC_SUCCESS);
7407 }
7408 
7409 /*@
7410   MatGetBlockSizes - Returns the matrix block row and column sizes.
7411 
7412   Not Collective
7413 
7414   Input Parameter:
7415 . mat - the matrix
7416 
7417   Output Parameters:
7418 + rbs - row block size
7419 - cbs - column block size
7420 
7421   Level: intermediate
7422 
7423   Notes:
7424   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7425   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7426 
7427   If a block size has not been set yet this routine returns 1.
7428 
7429 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7430 @*/
7431 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7432 {
7433   PetscFunctionBegin;
7434   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7435   if (rbs) PetscAssertPointer(rbs, 2);
7436   if (cbs) PetscAssertPointer(cbs, 3);
7437   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7438   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7439   PetscFunctionReturn(PETSC_SUCCESS);
7440 }
7441 
7442 /*@
7443   MatSetBlockSize - Sets the matrix block size.
7444 
7445   Logically Collective
7446 
7447   Input Parameters:
7448 + mat - the matrix
7449 - bs  - block size
7450 
7451   Level: intermediate
7452 
7453   Notes:
7454   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7455   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7456 
7457   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7458   is compatible with the matrix local sizes.
7459 
7460 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7461 @*/
7462 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7463 {
7464   PetscFunctionBegin;
7465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7466   PetscValidLogicalCollectiveInt(mat, bs, 2);
7467   PetscCall(MatSetBlockSizes(mat, bs, bs));
7468   PetscFunctionReturn(PETSC_SUCCESS);
7469 }
7470 
7471 typedef struct {
7472   PetscInt         n;
7473   IS              *is;
7474   Mat             *mat;
7475   PetscObjectState nonzerostate;
7476   Mat              C;
7477 } EnvelopeData;
7478 
7479 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7480 {
7481   EnvelopeData *edata = (EnvelopeData *)ptr;
7482 
7483   PetscFunctionBegin;
7484   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7485   PetscCall(PetscFree(edata->is));
7486   PetscCall(PetscFree(edata));
7487   PetscFunctionReturn(PETSC_SUCCESS);
7488 }
7489 
7490 /*@
7491   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7492   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7493 
7494   Collective
7495 
7496   Input Parameter:
7497 . mat - the matrix
7498 
7499   Level: intermediate
7500 
7501   Notes:
7502   There can be zeros within the blocks
7503 
7504   The blocks can overlap between processes, including laying on more than two processes
7505 
7506 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7507 @*/
7508 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7509 {
7510   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7511   PetscInt          *diag, *odiag, sc;
7512   VecScatter         scatter;
7513   PetscScalar       *seqv;
7514   const PetscScalar *parv;
7515   const PetscInt    *ia, *ja;
7516   PetscBool          set, flag, done;
7517   Mat                AA = mat, A;
7518   MPI_Comm           comm;
7519   PetscMPIInt        rank, size, tag;
7520   MPI_Status         status;
7521   PetscContainer     container;
7522   EnvelopeData      *edata;
7523   Vec                seq, par;
7524   IS                 isglobal;
7525 
7526   PetscFunctionBegin;
7527   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7528   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7529   if (!set || !flag) {
7530     /* TODO: only needs nonzero structure of transpose */
7531     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7532     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7533   }
7534   PetscCall(MatAIJGetLocalMat(AA, &A));
7535   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7536   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7537 
7538   PetscCall(MatGetLocalSize(mat, &n, NULL));
7539   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7540   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7541   PetscCallMPI(MPI_Comm_size(comm, &size));
7542   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7543 
7544   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7545 
7546   if (rank > 0) {
7547     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7548     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7549   }
7550   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7551   for (i = 0; i < n; i++) {
7552     env = PetscMax(env, ja[ia[i + 1] - 1]);
7553     II  = rstart + i;
7554     if (env == II) {
7555       starts[lblocks]  = tbs;
7556       sizes[lblocks++] = 1 + II - tbs;
7557       tbs              = 1 + II;
7558     }
7559   }
7560   if (rank < size - 1) {
7561     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7562     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7563   }
7564 
7565   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7566   if (!set || !flag) PetscCall(MatDestroy(&AA));
7567   PetscCall(MatDestroy(&A));
7568 
7569   PetscCall(PetscNew(&edata));
7570   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7571   edata->n = lblocks;
7572   /* create IS needed for extracting blocks from the original matrix */
7573   PetscCall(PetscMalloc1(lblocks, &edata->is));
7574   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7575 
7576   /* Create the resulting inverse matrix structure with preallocation information */
7577   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7578   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7579   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7580   PetscCall(MatSetType(edata->C, MATAIJ));
7581 
7582   /* Communicate the start and end of each row, from each block to the correct rank */
7583   /* TODO: Use PetscSF instead of VecScatter */
7584   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7585   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7586   PetscCall(VecGetArrayWrite(seq, &seqv));
7587   for (PetscInt i = 0; i < lblocks; i++) {
7588     for (PetscInt j = 0; j < sizes[i]; j++) {
7589       seqv[cnt]     = starts[i];
7590       seqv[cnt + 1] = starts[i] + sizes[i];
7591       cnt += 2;
7592     }
7593   }
7594   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7595   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7596   sc -= cnt;
7597   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7598   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7599   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7600   PetscCall(ISDestroy(&isglobal));
7601   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7602   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7603   PetscCall(VecScatterDestroy(&scatter));
7604   PetscCall(VecDestroy(&seq));
7605   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7606   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7607   PetscCall(VecGetArrayRead(par, &parv));
7608   cnt = 0;
7609   PetscCall(MatGetSize(mat, NULL, &n));
7610   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7611     PetscInt start, end, d = 0, od = 0;
7612 
7613     start = (PetscInt)PetscRealPart(parv[cnt]);
7614     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7615     cnt += 2;
7616 
7617     if (start < cstart) {
7618       od += cstart - start + n - cend;
7619       d += cend - cstart;
7620     } else if (start < cend) {
7621       od += n - cend;
7622       d += cend - start;
7623     } else od += n - start;
7624     if (end <= cstart) {
7625       od -= cstart - end + n - cend;
7626       d -= cend - cstart;
7627     } else if (end < cend) {
7628       od -= n - cend;
7629       d -= cend - end;
7630     } else od -= n - end;
7631 
7632     odiag[i] = od;
7633     diag[i]  = d;
7634   }
7635   PetscCall(VecRestoreArrayRead(par, &parv));
7636   PetscCall(VecDestroy(&par));
7637   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7638   PetscCall(PetscFree2(diag, odiag));
7639   PetscCall(PetscFree2(sizes, starts));
7640 
7641   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7642   PetscCall(PetscContainerSetPointer(container, edata));
7643   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7644   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7645   PetscCall(PetscObjectDereference((PetscObject)container));
7646   PetscFunctionReturn(PETSC_SUCCESS);
7647 }
7648 
7649 /*@
7650   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7651 
7652   Collective
7653 
7654   Input Parameters:
7655 + A     - the matrix
7656 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7657 
7658   Output Parameter:
7659 . C - matrix with inverted block diagonal of `A`
7660 
7661   Level: advanced
7662 
7663   Note:
7664   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7665 
7666 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7667 @*/
7668 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7669 {
7670   PetscContainer   container;
7671   EnvelopeData    *edata;
7672   PetscObjectState nonzerostate;
7673 
7674   PetscFunctionBegin;
7675   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7676   if (!container) {
7677     PetscCall(MatComputeVariableBlockEnvelope(A));
7678     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7679   }
7680   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7681   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7682   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7683   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7684 
7685   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7686   *C = edata->C;
7687 
7688   for (PetscInt i = 0; i < edata->n; i++) {
7689     Mat          D;
7690     PetscScalar *dvalues;
7691 
7692     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7693     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7694     PetscCall(MatSeqDenseInvert(D));
7695     PetscCall(MatDenseGetArray(D, &dvalues));
7696     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7697     PetscCall(MatDestroy(&D));
7698   }
7699   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7700   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7701   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7702   PetscFunctionReturn(PETSC_SUCCESS);
7703 }
7704 
7705 /*@
7706   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7707 
7708   Logically Collective
7709 
7710   Input Parameters:
7711 + mat     - the matrix
7712 . nblocks - the number of blocks on this process, each block can only exist on a single process
7713 - bsizes  - the block sizes
7714 
7715   Level: intermediate
7716 
7717   Notes:
7718   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7719 
7720   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.
7721 
7722 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7723           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7724 @*/
7725 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7726 {
7727   PetscInt i, ncnt = 0, nlocal;
7728 
7729   PetscFunctionBegin;
7730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7731   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7732   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7733   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7734   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);
7735   PetscCall(PetscFree(mat->bsizes));
7736   mat->nblocks = nblocks;
7737   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7738   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7739   PetscFunctionReturn(PETSC_SUCCESS);
7740 }
7741 
7742 /*@C
7743   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7744 
7745   Logically Collective; No Fortran Support
7746 
7747   Input Parameter:
7748 . mat - the matrix
7749 
7750   Output Parameters:
7751 + nblocks - the number of blocks on this process
7752 - bsizes  - the block sizes
7753 
7754   Level: intermediate
7755 
7756 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7757 @*/
7758 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7759 {
7760   PetscFunctionBegin;
7761   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7762   *nblocks = mat->nblocks;
7763   *bsizes  = mat->bsizes;
7764   PetscFunctionReturn(PETSC_SUCCESS);
7765 }
7766 
7767 /*@
7768   MatSetBlockSizes - Sets the matrix block row and column sizes.
7769 
7770   Logically Collective
7771 
7772   Input Parameters:
7773 + mat - the matrix
7774 . rbs - row block size
7775 - cbs - column block size
7776 
7777   Level: intermediate
7778 
7779   Notes:
7780   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7781   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7782   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7783 
7784   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7785   are compatible with the matrix local sizes.
7786 
7787   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7788 
7789 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7790 @*/
7791 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7792 {
7793   PetscFunctionBegin;
7794   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7795   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7796   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7797   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7798   if (mat->rmap->refcnt) {
7799     ISLocalToGlobalMapping l2g  = NULL;
7800     PetscLayout            nmap = NULL;
7801 
7802     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7803     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7804     PetscCall(PetscLayoutDestroy(&mat->rmap));
7805     mat->rmap          = nmap;
7806     mat->rmap->mapping = l2g;
7807   }
7808   if (mat->cmap->refcnt) {
7809     ISLocalToGlobalMapping l2g  = NULL;
7810     PetscLayout            nmap = NULL;
7811 
7812     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7813     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7814     PetscCall(PetscLayoutDestroy(&mat->cmap));
7815     mat->cmap          = nmap;
7816     mat->cmap->mapping = l2g;
7817   }
7818   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7819   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7820   PetscFunctionReturn(PETSC_SUCCESS);
7821 }
7822 
7823 /*@
7824   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7825 
7826   Logically Collective
7827 
7828   Input Parameters:
7829 + mat     - the matrix
7830 . fromRow - matrix from which to copy row block size
7831 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7832 
7833   Level: developer
7834 
7835 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7836 @*/
7837 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7838 {
7839   PetscFunctionBegin;
7840   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7841   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7842   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7843   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7844   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7845   PetscFunctionReturn(PETSC_SUCCESS);
7846 }
7847 
7848 /*@
7849   MatResidual - Default routine to calculate the residual r = b - Ax
7850 
7851   Collective
7852 
7853   Input Parameters:
7854 + mat - the matrix
7855 . b   - the right-hand-side
7856 - x   - the approximate solution
7857 
7858   Output Parameter:
7859 . r - location to store the residual
7860 
7861   Level: developer
7862 
7863 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7864 @*/
7865 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7866 {
7867   PetscFunctionBegin;
7868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7869   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7870   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7871   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7872   PetscValidType(mat, 1);
7873   MatCheckPreallocated(mat, 1);
7874   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7875   if (!mat->ops->residual) {
7876     PetscCall(MatMult(mat, x, r));
7877     PetscCall(VecAYPX(r, -1.0, b));
7878   } else {
7879     PetscUseTypeMethod(mat, residual, b, x, r);
7880   }
7881   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7882   PetscFunctionReturn(PETSC_SUCCESS);
7883 }
7884 
7885 /*MC
7886     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7887 
7888     Synopsis:
7889     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7890 
7891     Not Collective
7892 
7893     Input Parameters:
7894 +   A - the matrix
7895 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7896 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7897 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7898                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7899                  always used.
7900 
7901     Output Parameters:
7902 +   n - number of local rows in the (possibly compressed) matrix
7903 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7904 .   ja - the column indices
7905 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7906            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7907 
7908     Level: developer
7909 
7910     Note:
7911     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7912 
7913 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7914 M*/
7915 
7916 /*MC
7917     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7918 
7919     Synopsis:
7920     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7921 
7922     Not Collective
7923 
7924     Input Parameters:
7925 +   A - the  matrix
7926 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7927 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7928     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7929                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7930                  always used.
7931 .   n - number of local rows in the (possibly compressed) matrix
7932 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7933 .   ja - the column indices
7934 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7935            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7936 
7937     Level: developer
7938 
7939 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7940 M*/
7941 
7942 /*@C
7943   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7944 
7945   Collective
7946 
7947   Input Parameters:
7948 + mat             - the matrix
7949 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7950 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7951 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7952                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7953                  always used.
7954 
7955   Output Parameters:
7956 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7957 . 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
7958 . ja   - the column indices, use `NULL` if not needed
7959 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7960            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7961 
7962   Level: developer
7963 
7964   Notes:
7965   You CANNOT change any of the ia[] or ja[] values.
7966 
7967   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7968 
7969   Fortran Notes:
7970   Use
7971 .vb
7972     PetscInt, pointer :: ia(:),ja(:)
7973     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7974     ! Access the ith and jth entries via ia(i) and ja(j)
7975 .ve
7976 
7977   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7978 
7979 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7980 @*/
7981 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7982 {
7983   PetscFunctionBegin;
7984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7985   PetscValidType(mat, 1);
7986   if (n) PetscAssertPointer(n, 5);
7987   if (ia) PetscAssertPointer(ia, 6);
7988   if (ja) PetscAssertPointer(ja, 7);
7989   if (done) PetscAssertPointer(done, 8);
7990   MatCheckPreallocated(mat, 1);
7991   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7992   else {
7993     if (done) *done = PETSC_TRUE;
7994     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7995     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7996     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7997   }
7998   PetscFunctionReturn(PETSC_SUCCESS);
7999 }
8000 
8001 /*@C
8002   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8003 
8004   Collective
8005 
8006   Input Parameters:
8007 + mat             - the matrix
8008 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8009 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8010                 symmetrized
8011 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8012                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8013                  always used.
8014 . n               - number of columns in the (possibly compressed) matrix
8015 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8016 - ja              - the row indices
8017 
8018   Output Parameter:
8019 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8020 
8021   Level: developer
8022 
8023 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8024 @*/
8025 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8026 {
8027   PetscFunctionBegin;
8028   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8029   PetscValidType(mat, 1);
8030   PetscAssertPointer(n, 5);
8031   if (ia) PetscAssertPointer(ia, 6);
8032   if (ja) PetscAssertPointer(ja, 7);
8033   PetscAssertPointer(done, 8);
8034   MatCheckPreallocated(mat, 1);
8035   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8036   else {
8037     *done = PETSC_TRUE;
8038     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8039   }
8040   PetscFunctionReturn(PETSC_SUCCESS);
8041 }
8042 
8043 /*@C
8044   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8045 
8046   Collective
8047 
8048   Input Parameters:
8049 + mat             - the matrix
8050 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8051 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8052 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8053                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8054                  always used.
8055 . n               - size of (possibly compressed) matrix
8056 . ia              - the row pointers
8057 - ja              - the column indices
8058 
8059   Output Parameter:
8060 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8061 
8062   Level: developer
8063 
8064   Note:
8065   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8066   us of the array after it has been restored. If you pass `NULL`, it will
8067   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8068 
8069   Fortran Note:
8070   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8071 
8072 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8073 @*/
8074 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8075 {
8076   PetscFunctionBegin;
8077   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8078   PetscValidType(mat, 1);
8079   if (ia) PetscAssertPointer(ia, 6);
8080   if (ja) PetscAssertPointer(ja, 7);
8081   if (done) PetscAssertPointer(done, 8);
8082   MatCheckPreallocated(mat, 1);
8083 
8084   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8085   else {
8086     if (done) *done = PETSC_TRUE;
8087     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8088     if (n) *n = 0;
8089     if (ia) *ia = NULL;
8090     if (ja) *ja = NULL;
8091   }
8092   PetscFunctionReturn(PETSC_SUCCESS);
8093 }
8094 
8095 /*@C
8096   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8097 
8098   Collective
8099 
8100   Input Parameters:
8101 + mat             - the matrix
8102 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8103 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8104 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8105                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8106                  always used.
8107 
8108   Output Parameters:
8109 + n    - size of (possibly compressed) matrix
8110 . ia   - the column pointers
8111 . ja   - the row indices
8112 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8113 
8114   Level: developer
8115 
8116 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8117 @*/
8118 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8119 {
8120   PetscFunctionBegin;
8121   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8122   PetscValidType(mat, 1);
8123   if (ia) PetscAssertPointer(ia, 6);
8124   if (ja) PetscAssertPointer(ja, 7);
8125   PetscAssertPointer(done, 8);
8126   MatCheckPreallocated(mat, 1);
8127 
8128   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8129   else {
8130     *done = PETSC_TRUE;
8131     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8132     if (n) *n = 0;
8133     if (ia) *ia = NULL;
8134     if (ja) *ja = NULL;
8135   }
8136   PetscFunctionReturn(PETSC_SUCCESS);
8137 }
8138 
8139 /*@C
8140   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8141   `MatGetColumnIJ()`.
8142 
8143   Collective
8144 
8145   Input Parameters:
8146 + mat        - the matrix
8147 . ncolors    - maximum color value
8148 . n          - number of entries in colorarray
8149 - colorarray - array indicating color for each column
8150 
8151   Output Parameter:
8152 . iscoloring - coloring generated using colorarray information
8153 
8154   Level: developer
8155 
8156 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8157 @*/
8158 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8159 {
8160   PetscFunctionBegin;
8161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8162   PetscValidType(mat, 1);
8163   PetscAssertPointer(colorarray, 4);
8164   PetscAssertPointer(iscoloring, 5);
8165   MatCheckPreallocated(mat, 1);
8166 
8167   if (!mat->ops->coloringpatch) {
8168     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8169   } else {
8170     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8171   }
8172   PetscFunctionReturn(PETSC_SUCCESS);
8173 }
8174 
8175 /*@
8176   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8177 
8178   Logically Collective
8179 
8180   Input Parameter:
8181 . mat - the factored matrix to be reset
8182 
8183   Level: developer
8184 
8185   Notes:
8186   This routine should be used only with factored matrices formed by in-place
8187   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8188   format).  This option can save memory, for example, when solving nonlinear
8189   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8190   ILU(0) preconditioner.
8191 
8192   One can specify in-place ILU(0) factorization by calling
8193 .vb
8194      PCType(pc,PCILU);
8195      PCFactorSeUseInPlace(pc);
8196 .ve
8197   or by using the options -pc_type ilu -pc_factor_in_place
8198 
8199   In-place factorization ILU(0) can also be used as a local
8200   solver for the blocks within the block Jacobi or additive Schwarz
8201   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8202   for details on setting local solver options.
8203 
8204   Most users should employ the `KSP` interface for linear solvers
8205   instead of working directly with matrix algebra routines such as this.
8206   See, e.g., `KSPCreate()`.
8207 
8208 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8209 @*/
8210 PetscErrorCode MatSetUnfactored(Mat mat)
8211 {
8212   PetscFunctionBegin;
8213   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8214   PetscValidType(mat, 1);
8215   MatCheckPreallocated(mat, 1);
8216   mat->factortype = MAT_FACTOR_NONE;
8217   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8218   PetscUseTypeMethod(mat, setunfactored);
8219   PetscFunctionReturn(PETSC_SUCCESS);
8220 }
8221 
8222 /*MC
8223     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8224 
8225     Synopsis:
8226     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8227 
8228     Not Collective
8229 
8230     Input Parameter:
8231 .   x - matrix
8232 
8233     Output Parameters:
8234 +   xx_v - the Fortran pointer to the array
8235 -   ierr - error code
8236 
8237     Example of Usage:
8238 .vb
8239       PetscScalar, pointer xx_v(:,:)
8240       ....
8241       call MatDenseGetArrayF90(x,xx_v,ierr)
8242       a = xx_v(3)
8243       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8244 .ve
8245 
8246     Level: advanced
8247 
8248 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8249 M*/
8250 
8251 /*MC
8252     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8253     accessed with `MatDenseGetArrayF90()`.
8254 
8255     Synopsis:
8256     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8257 
8258     Not Collective
8259 
8260     Input Parameters:
8261 +   x - matrix
8262 -   xx_v - the Fortran90 pointer to the array
8263 
8264     Output Parameter:
8265 .   ierr - error code
8266 
8267     Example of Usage:
8268 .vb
8269        PetscScalar, pointer xx_v(:,:)
8270        ....
8271        call MatDenseGetArrayF90(x,xx_v,ierr)
8272        a = xx_v(3)
8273        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8274 .ve
8275 
8276     Level: advanced
8277 
8278 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8279 M*/
8280 
8281 /*MC
8282     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8283 
8284     Synopsis:
8285     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8286 
8287     Not Collective
8288 
8289     Input Parameter:
8290 .   x - matrix
8291 
8292     Output Parameters:
8293 +   xx_v - the Fortran pointer to the array
8294 -   ierr - error code
8295 
8296     Example of Usage:
8297 .vb
8298       PetscScalar, pointer xx_v(:)
8299       ....
8300       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8301       a = xx_v(3)
8302       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8303 .ve
8304 
8305     Level: advanced
8306 
8307 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8308 M*/
8309 
8310 /*MC
8311     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8312     accessed with `MatSeqAIJGetArrayF90()`.
8313 
8314     Synopsis:
8315     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8316 
8317     Not Collective
8318 
8319     Input Parameters:
8320 +   x - matrix
8321 -   xx_v - the Fortran90 pointer to the array
8322 
8323     Output Parameter:
8324 .   ierr - error code
8325 
8326     Example of Usage:
8327 .vb
8328        PetscScalar, pointer xx_v(:)
8329        ....
8330        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8331        a = xx_v(3)
8332        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8333 .ve
8334 
8335     Level: advanced
8336 
8337 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8338 M*/
8339 
8340 /*@
8341   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8342   as the original matrix.
8343 
8344   Collective
8345 
8346   Input Parameters:
8347 + mat   - the original matrix
8348 . isrow - parallel `IS` containing the rows this processor should obtain
8349 . 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.
8350 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8351 
8352   Output Parameter:
8353 . newmat - the new submatrix, of the same type as the original matrix
8354 
8355   Level: advanced
8356 
8357   Notes:
8358   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8359 
8360   Some matrix types place restrictions on the row and column indices, such
8361   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;
8362   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8363 
8364   The index sets may not have duplicate entries.
8365 
8366   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8367   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8368   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8369   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8370   you are finished using it.
8371 
8372   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8373   the input matrix.
8374 
8375   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8376 
8377   If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature
8378   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8379 
8380   Example usage:
8381   Consider the following 8x8 matrix with 34 non-zero values, that is
8382   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8383   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8384   as follows
8385 .vb
8386             1  2  0  |  0  3  0  |  0  4
8387     Proc0   0  5  6  |  7  0  0  |  8  0
8388             9  0 10  | 11  0  0  | 12  0
8389     -------------------------------------
8390            13  0 14  | 15 16 17  |  0  0
8391     Proc1   0 18  0  | 19 20 21  |  0  0
8392             0  0  0  | 22 23  0  | 24  0
8393     -------------------------------------
8394     Proc2  25 26 27  |  0  0 28  | 29  0
8395            30  0  0  | 31 32 33  |  0 34
8396 .ve
8397 
8398   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8399 
8400 .vb
8401             2  0  |  0  3  0  |  0
8402     Proc0   5  6  |  7  0  0  |  8
8403     -------------------------------
8404     Proc1  18  0  | 19 20 21  |  0
8405     -------------------------------
8406     Proc2  26 27  |  0  0 28  | 29
8407             0  0  | 31 32 33  |  0
8408 .ve
8409 
8410 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8411 @*/
8412 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8413 {
8414   PetscMPIInt size;
8415   Mat        *local;
8416   IS          iscoltmp;
8417   PetscBool   flg;
8418 
8419   PetscFunctionBegin;
8420   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8421   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8422   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8423   PetscAssertPointer(newmat, 5);
8424   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8425   PetscValidType(mat, 1);
8426   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8427   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8428 
8429   MatCheckPreallocated(mat, 1);
8430   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8431 
8432   if (!iscol || isrow == iscol) {
8433     PetscBool   stride;
8434     PetscMPIInt grabentirematrix = 0, grab;
8435     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8436     if (stride) {
8437       PetscInt first, step, n, rstart, rend;
8438       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8439       if (step == 1) {
8440         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8441         if (rstart == first) {
8442           PetscCall(ISGetLocalSize(isrow, &n));
8443           if (n == rend - rstart) grabentirematrix = 1;
8444         }
8445       }
8446     }
8447     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8448     if (grab) {
8449       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8450       if (cll == MAT_INITIAL_MATRIX) {
8451         *newmat = mat;
8452         PetscCall(PetscObjectReference((PetscObject)mat));
8453       }
8454       PetscFunctionReturn(PETSC_SUCCESS);
8455     }
8456   }
8457 
8458   if (!iscol) {
8459     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8460   } else {
8461     iscoltmp = iscol;
8462   }
8463 
8464   /* if original matrix is on just one processor then use submatrix generated */
8465   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8466     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8467     goto setproperties;
8468   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8469     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8470     *newmat = *local;
8471     PetscCall(PetscFree(local));
8472     goto setproperties;
8473   } else if (!mat->ops->createsubmatrix) {
8474     /* Create a new matrix type that implements the operation using the full matrix */
8475     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8476     switch (cll) {
8477     case MAT_INITIAL_MATRIX:
8478       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8479       break;
8480     case MAT_REUSE_MATRIX:
8481       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8482       break;
8483     default:
8484       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8485     }
8486     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8487     goto setproperties;
8488   }
8489 
8490   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8491   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8492   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8493 
8494 setproperties:
8495   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8496   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8497   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8498   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8499   PetscFunctionReturn(PETSC_SUCCESS);
8500 }
8501 
8502 /*@
8503   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8504 
8505   Not Collective
8506 
8507   Input Parameters:
8508 + A - the matrix we wish to propagate options from
8509 - B - the matrix we wish to propagate options to
8510 
8511   Level: beginner
8512 
8513   Note:
8514   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8515 
8516 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8517 @*/
8518 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8519 {
8520   PetscFunctionBegin;
8521   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8522   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8523   B->symmetry_eternal            = A->symmetry_eternal;
8524   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8525   B->symmetric                   = A->symmetric;
8526   B->structurally_symmetric      = A->structurally_symmetric;
8527   B->spd                         = A->spd;
8528   B->hermitian                   = A->hermitian;
8529   PetscFunctionReturn(PETSC_SUCCESS);
8530 }
8531 
8532 /*@
8533   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8534   used during the assembly process to store values that belong to
8535   other processors.
8536 
8537   Not Collective
8538 
8539   Input Parameters:
8540 + mat   - the matrix
8541 . size  - the initial size of the stash.
8542 - bsize - the initial size of the block-stash(if used).
8543 
8544   Options Database Keys:
8545 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8546 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8547 
8548   Level: intermediate
8549 
8550   Notes:
8551   The block-stash is used for values set with `MatSetValuesBlocked()` while
8552   the stash is used for values set with `MatSetValues()`
8553 
8554   Run with the option -info and look for output of the form
8555   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8556   to determine the appropriate value, MM, to use for size and
8557   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8558   to determine the value, BMM to use for bsize
8559 
8560 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8561 @*/
8562 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8563 {
8564   PetscFunctionBegin;
8565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8566   PetscValidType(mat, 1);
8567   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8568   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8569   PetscFunctionReturn(PETSC_SUCCESS);
8570 }
8571 
8572 /*@
8573   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8574   the matrix
8575 
8576   Neighbor-wise Collective
8577 
8578   Input Parameters:
8579 + A - the matrix
8580 . x - the vector to be multiplied by the interpolation operator
8581 - y - the vector to be added to the result
8582 
8583   Output Parameter:
8584 . w - the resulting vector
8585 
8586   Level: intermediate
8587 
8588   Notes:
8589   `w` may be the same vector as `y`.
8590 
8591   This allows one to use either the restriction or interpolation (its transpose)
8592   matrix to do the interpolation
8593 
8594 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8595 @*/
8596 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8597 {
8598   PetscInt M, N, Ny;
8599 
8600   PetscFunctionBegin;
8601   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8602   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8603   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8604   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8605   PetscCall(MatGetSize(A, &M, &N));
8606   PetscCall(VecGetSize(y, &Ny));
8607   if (M == Ny) {
8608     PetscCall(MatMultAdd(A, x, y, w));
8609   } else {
8610     PetscCall(MatMultTransposeAdd(A, x, y, w));
8611   }
8612   PetscFunctionReturn(PETSC_SUCCESS);
8613 }
8614 
8615 /*@
8616   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8617   the matrix
8618 
8619   Neighbor-wise Collective
8620 
8621   Input Parameters:
8622 + A - the matrix
8623 - x - the vector to be interpolated
8624 
8625   Output Parameter:
8626 . y - the resulting vector
8627 
8628   Level: intermediate
8629 
8630   Note:
8631   This allows one to use either the restriction or interpolation (its transpose)
8632   matrix to do the interpolation
8633 
8634 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8635 @*/
8636 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8637 {
8638   PetscInt M, N, Ny;
8639 
8640   PetscFunctionBegin;
8641   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8642   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8643   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8644   PetscCall(MatGetSize(A, &M, &N));
8645   PetscCall(VecGetSize(y, &Ny));
8646   if (M == Ny) {
8647     PetscCall(MatMult(A, x, y));
8648   } else {
8649     PetscCall(MatMultTranspose(A, x, y));
8650   }
8651   PetscFunctionReturn(PETSC_SUCCESS);
8652 }
8653 
8654 /*@
8655   MatRestrict - $y = A*x$ or $A^T*x$
8656 
8657   Neighbor-wise Collective
8658 
8659   Input Parameters:
8660 + A - the matrix
8661 - x - the vector to be restricted
8662 
8663   Output Parameter:
8664 . y - the resulting vector
8665 
8666   Level: intermediate
8667 
8668   Note:
8669   This allows one to use either the restriction or interpolation (its transpose)
8670   matrix to do the restriction
8671 
8672 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8673 @*/
8674 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8675 {
8676   PetscInt M, N, Ny;
8677 
8678   PetscFunctionBegin;
8679   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8680   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8681   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8682   PetscCall(MatGetSize(A, &M, &N));
8683   PetscCall(VecGetSize(y, &Ny));
8684   if (M == Ny) {
8685     PetscCall(MatMult(A, x, y));
8686   } else {
8687     PetscCall(MatMultTranspose(A, x, y));
8688   }
8689   PetscFunctionReturn(PETSC_SUCCESS);
8690 }
8691 
8692 /*@
8693   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8694 
8695   Neighbor-wise Collective
8696 
8697   Input Parameters:
8698 + A - the matrix
8699 . x - the input dense matrix to be multiplied
8700 - w - the input dense matrix to be added to the result
8701 
8702   Output Parameter:
8703 . y - the output dense matrix
8704 
8705   Level: intermediate
8706 
8707   Note:
8708   This allows one to use either the restriction or interpolation (its transpose)
8709   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8710   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8711 
8712 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8713 @*/
8714 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8715 {
8716   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8717   PetscBool trans = PETSC_TRUE;
8718   MatReuse  reuse = MAT_INITIAL_MATRIX;
8719 
8720   PetscFunctionBegin;
8721   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8722   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8723   PetscValidType(x, 2);
8724   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8725   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8726   PetscCall(MatGetSize(A, &M, &N));
8727   PetscCall(MatGetSize(x, &Mx, &Nx));
8728   if (N == Mx) trans = PETSC_FALSE;
8729   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);
8730   Mo = trans ? N : M;
8731   if (*y) {
8732     PetscCall(MatGetSize(*y, &My, &Ny));
8733     if (Mo == My && Nx == Ny) {
8734       reuse = MAT_REUSE_MATRIX;
8735     } else {
8736       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);
8737       PetscCall(MatDestroy(y));
8738     }
8739   }
8740 
8741   if (w && *y == w) { /* this is to minimize changes in PCMG */
8742     PetscBool flg;
8743 
8744     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8745     if (w) {
8746       PetscInt My, Ny, Mw, Nw;
8747 
8748       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8749       PetscCall(MatGetSize(*y, &My, &Ny));
8750       PetscCall(MatGetSize(w, &Mw, &Nw));
8751       if (!flg || My != Mw || Ny != Nw) w = NULL;
8752     }
8753     if (!w) {
8754       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8755       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8756       PetscCall(PetscObjectDereference((PetscObject)w));
8757     } else {
8758       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8759     }
8760   }
8761   if (!trans) {
8762     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8763   } else {
8764     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8765   }
8766   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8767   PetscFunctionReturn(PETSC_SUCCESS);
8768 }
8769 
8770 /*@
8771   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8772 
8773   Neighbor-wise Collective
8774 
8775   Input Parameters:
8776 + A - the matrix
8777 - x - the input dense matrix
8778 
8779   Output Parameter:
8780 . y - the output dense matrix
8781 
8782   Level: intermediate
8783 
8784   Note:
8785   This allows one to use either the restriction or interpolation (its transpose)
8786   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8787   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8788 
8789 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8790 @*/
8791 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8792 {
8793   PetscFunctionBegin;
8794   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8795   PetscFunctionReturn(PETSC_SUCCESS);
8796 }
8797 
8798 /*@
8799   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8800 
8801   Neighbor-wise Collective
8802 
8803   Input Parameters:
8804 + A - the matrix
8805 - x - the input dense matrix
8806 
8807   Output Parameter:
8808 . y - the output dense matrix
8809 
8810   Level: intermediate
8811 
8812   Note:
8813   This allows one to use either the restriction or interpolation (its transpose)
8814   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8815   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8816 
8817 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8818 @*/
8819 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8820 {
8821   PetscFunctionBegin;
8822   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8823   PetscFunctionReturn(PETSC_SUCCESS);
8824 }
8825 
8826 /*@
8827   MatGetNullSpace - retrieves the null space of a matrix.
8828 
8829   Logically Collective
8830 
8831   Input Parameters:
8832 + mat    - the matrix
8833 - nullsp - the null space object
8834 
8835   Level: developer
8836 
8837 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8838 @*/
8839 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8840 {
8841   PetscFunctionBegin;
8842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8843   PetscAssertPointer(nullsp, 2);
8844   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8845   PetscFunctionReturn(PETSC_SUCCESS);
8846 }
8847 
8848 /*@
8849   MatSetNullSpace - attaches a null space to a matrix.
8850 
8851   Logically Collective
8852 
8853   Input Parameters:
8854 + mat    - the matrix
8855 - nullsp - the null space object
8856 
8857   Level: advanced
8858 
8859   Notes:
8860   This null space is used by the `KSP` linear solvers to solve singular systems.
8861 
8862   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`
8863 
8864   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
8865   to zero but the linear system will still be solved in a least squares sense.
8866 
8867   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8868   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)$.
8869   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
8870   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
8871   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$).
8872   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8873 
8874   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8875   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8876   routine also automatically calls `MatSetTransposeNullSpace()`.
8877 
8878   The user should call `MatNullSpaceDestroy()`.
8879 
8880 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8881           `KSPSetPCSide()`
8882 @*/
8883 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8884 {
8885   PetscFunctionBegin;
8886   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8887   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8888   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8889   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8890   mat->nullsp = nullsp;
8891   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8892   PetscFunctionReturn(PETSC_SUCCESS);
8893 }
8894 
8895 /*@
8896   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8897 
8898   Logically Collective
8899 
8900   Input Parameters:
8901 + mat    - the matrix
8902 - nullsp - the null space object
8903 
8904   Level: developer
8905 
8906 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8907 @*/
8908 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8909 {
8910   PetscFunctionBegin;
8911   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8912   PetscValidType(mat, 1);
8913   PetscAssertPointer(nullsp, 2);
8914   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8915   PetscFunctionReturn(PETSC_SUCCESS);
8916 }
8917 
8918 /*@
8919   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8920 
8921   Logically Collective
8922 
8923   Input Parameters:
8924 + mat    - the matrix
8925 - nullsp - the null space object
8926 
8927   Level: advanced
8928 
8929   Notes:
8930   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8931 
8932   See `MatSetNullSpace()`
8933 
8934 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8935 @*/
8936 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8937 {
8938   PetscFunctionBegin;
8939   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8940   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8941   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8942   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8943   mat->transnullsp = nullsp;
8944   PetscFunctionReturn(PETSC_SUCCESS);
8945 }
8946 
8947 /*@
8948   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8949   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8950 
8951   Logically Collective
8952 
8953   Input Parameters:
8954 + mat    - the matrix
8955 - nullsp - the null space object
8956 
8957   Level: advanced
8958 
8959   Notes:
8960   Overwrites any previous near null space that may have been attached
8961 
8962   You can remove the null space by calling this routine with an `nullsp` of `NULL`
8963 
8964 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8965 @*/
8966 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8967 {
8968   PetscFunctionBegin;
8969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8970   PetscValidType(mat, 1);
8971   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8972   MatCheckPreallocated(mat, 1);
8973   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8974   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8975   mat->nearnullsp = nullsp;
8976   PetscFunctionReturn(PETSC_SUCCESS);
8977 }
8978 
8979 /*@
8980   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8981 
8982   Not Collective
8983 
8984   Input Parameter:
8985 . mat - the matrix
8986 
8987   Output Parameter:
8988 . nullsp - the null space object, `NULL` if not set
8989 
8990   Level: advanced
8991 
8992 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8993 @*/
8994 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8995 {
8996   PetscFunctionBegin;
8997   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8998   PetscValidType(mat, 1);
8999   PetscAssertPointer(nullsp, 2);
9000   MatCheckPreallocated(mat, 1);
9001   *nullsp = mat->nearnullsp;
9002   PetscFunctionReturn(PETSC_SUCCESS);
9003 }
9004 
9005 /*@C
9006   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9007 
9008   Collective
9009 
9010   Input Parameters:
9011 + mat  - the matrix
9012 . row  - row/column permutation
9013 - info - information on desired factorization process
9014 
9015   Level: developer
9016 
9017   Notes:
9018   Probably really in-place only when level of fill is zero, otherwise allocates
9019   new space to store factored matrix and deletes previous memory.
9020 
9021   Most users should employ the `KSP` interface for linear solvers
9022   instead of working directly with matrix algebra routines such as this.
9023   See, e.g., `KSPCreate()`.
9024 
9025   Developer Note:
9026   The Fortran interface is not autogenerated as the
9027   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9028 
9029 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9030 @*/
9031 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9032 {
9033   PetscFunctionBegin;
9034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9035   PetscValidType(mat, 1);
9036   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9037   PetscAssertPointer(info, 3);
9038   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9041   MatCheckPreallocated(mat, 1);
9042   PetscUseTypeMethod(mat, iccfactor, row, info);
9043   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9044   PetscFunctionReturn(PETSC_SUCCESS);
9045 }
9046 
9047 /*@
9048   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9049   ghosted ones.
9050 
9051   Not Collective
9052 
9053   Input Parameters:
9054 + mat  - the matrix
9055 - diag - the diagonal values, including ghost ones
9056 
9057   Level: developer
9058 
9059   Notes:
9060   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9061 
9062   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9063 
9064 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9065 @*/
9066 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9067 {
9068   PetscMPIInt size;
9069 
9070   PetscFunctionBegin;
9071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9072   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9073   PetscValidType(mat, 1);
9074 
9075   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9076   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9077   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9078   if (size == 1) {
9079     PetscInt n, m;
9080     PetscCall(VecGetSize(diag, &n));
9081     PetscCall(MatGetSize(mat, NULL, &m));
9082     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9083     PetscCall(MatDiagonalScale(mat, NULL, diag));
9084   } else {
9085     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9086   }
9087   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9088   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9089   PetscFunctionReturn(PETSC_SUCCESS);
9090 }
9091 
9092 /*@
9093   MatGetInertia - Gets the inertia from a factored matrix
9094 
9095   Collective
9096 
9097   Input Parameter:
9098 . mat - the matrix
9099 
9100   Output Parameters:
9101 + nneg  - number of negative eigenvalues
9102 . nzero - number of zero eigenvalues
9103 - npos  - number of positive eigenvalues
9104 
9105   Level: advanced
9106 
9107   Note:
9108   Matrix must have been factored by `MatCholeskyFactor()`
9109 
9110 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9111 @*/
9112 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9113 {
9114   PetscFunctionBegin;
9115   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9116   PetscValidType(mat, 1);
9117   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9118   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9119   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9120   PetscFunctionReturn(PETSC_SUCCESS);
9121 }
9122 
9123 /*@C
9124   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9125 
9126   Neighbor-wise Collective
9127 
9128   Input Parameters:
9129 + mat - the factored matrix obtained with `MatGetFactor()`
9130 - b   - the right-hand-side vectors
9131 
9132   Output Parameter:
9133 . x - the result vectors
9134 
9135   Level: developer
9136 
9137   Note:
9138   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9139   call `MatSolves`(A,x,x).
9140 
9141 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9142 @*/
9143 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9144 {
9145   PetscFunctionBegin;
9146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9147   PetscValidType(mat, 1);
9148   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9149   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9150   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9151 
9152   MatCheckPreallocated(mat, 1);
9153   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9154   PetscUseTypeMethod(mat, solves, b, x);
9155   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9156   PetscFunctionReturn(PETSC_SUCCESS);
9157 }
9158 
9159 /*@
9160   MatIsSymmetric - Test whether a matrix is symmetric
9161 
9162   Collective
9163 
9164   Input Parameters:
9165 + A   - the matrix to test
9166 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9167 
9168   Output Parameter:
9169 . flg - the result
9170 
9171   Level: intermediate
9172 
9173   Notes:
9174   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9175 
9176   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9177 
9178   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9179   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9180 
9181 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9182           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9183 @*/
9184 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9185 {
9186   PetscFunctionBegin;
9187   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9188   PetscAssertPointer(flg, 3);
9189 
9190   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9191   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9192   else {
9193     PetscUseTypeMethod(A, issymmetric, tol, flg);
9194     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9195   }
9196   PetscFunctionReturn(PETSC_SUCCESS);
9197 }
9198 
9199 /*@
9200   MatIsHermitian - Test whether a matrix is Hermitian
9201 
9202   Collective
9203 
9204   Input Parameters:
9205 + A   - the matrix to test
9206 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9207 
9208   Output Parameter:
9209 . flg - the result
9210 
9211   Level: intermediate
9212 
9213   Notes:
9214   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9215 
9216   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9217 
9218   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9219   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9220 
9221 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9222           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9223 @*/
9224 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9225 {
9226   PetscFunctionBegin;
9227   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9228   PetscAssertPointer(flg, 3);
9229 
9230   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9231   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9232   else {
9233     PetscUseTypeMethod(A, ishermitian, tol, flg);
9234     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9235   }
9236   PetscFunctionReturn(PETSC_SUCCESS);
9237 }
9238 
9239 /*@
9240   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9241 
9242   Not Collective
9243 
9244   Input Parameter:
9245 . A - the matrix to check
9246 
9247   Output Parameters:
9248 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9249 - flg - the result (only valid if set is `PETSC_TRUE`)
9250 
9251   Level: advanced
9252 
9253   Notes:
9254   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9255   if you want it explicitly checked
9256 
9257   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9258   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9259 
9260 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9261 @*/
9262 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9263 {
9264   PetscFunctionBegin;
9265   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9266   PetscAssertPointer(set, 2);
9267   PetscAssertPointer(flg, 3);
9268   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9269     *set = PETSC_TRUE;
9270     *flg = PetscBool3ToBool(A->symmetric);
9271   } else {
9272     *set = PETSC_FALSE;
9273   }
9274   PetscFunctionReturn(PETSC_SUCCESS);
9275 }
9276 
9277 /*@
9278   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9279 
9280   Not Collective
9281 
9282   Input Parameter:
9283 . A - the matrix to check
9284 
9285   Output Parameters:
9286 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9287 - flg - the result (only valid if set is `PETSC_TRUE`)
9288 
9289   Level: advanced
9290 
9291   Notes:
9292   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9293 
9294   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9295   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9296 
9297 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9298 @*/
9299 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9300 {
9301   PetscFunctionBegin;
9302   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9303   PetscAssertPointer(set, 2);
9304   PetscAssertPointer(flg, 3);
9305   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9306     *set = PETSC_TRUE;
9307     *flg = PetscBool3ToBool(A->spd);
9308   } else {
9309     *set = PETSC_FALSE;
9310   }
9311   PetscFunctionReturn(PETSC_SUCCESS);
9312 }
9313 
9314 /*@
9315   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9316 
9317   Not Collective
9318 
9319   Input Parameter:
9320 . A - the matrix to check
9321 
9322   Output Parameters:
9323 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9324 - flg - the result (only valid if set is `PETSC_TRUE`)
9325 
9326   Level: advanced
9327 
9328   Notes:
9329   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9330   if you want it explicitly checked
9331 
9332   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9333   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9334 
9335 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9336 @*/
9337 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9338 {
9339   PetscFunctionBegin;
9340   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9341   PetscAssertPointer(set, 2);
9342   PetscAssertPointer(flg, 3);
9343   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9344     *set = PETSC_TRUE;
9345     *flg = PetscBool3ToBool(A->hermitian);
9346   } else {
9347     *set = PETSC_FALSE;
9348   }
9349   PetscFunctionReturn(PETSC_SUCCESS);
9350 }
9351 
9352 /*@
9353   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9354 
9355   Collective
9356 
9357   Input Parameter:
9358 . A - the matrix to test
9359 
9360   Output Parameter:
9361 . flg - the result
9362 
9363   Level: intermediate
9364 
9365   Notes:
9366   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9367 
9368   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
9369   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9370 
9371 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9372 @*/
9373 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9374 {
9375   PetscFunctionBegin;
9376   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9377   PetscAssertPointer(flg, 2);
9378   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9379     *flg = PetscBool3ToBool(A->structurally_symmetric);
9380   } else {
9381     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9382     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9383   }
9384   PetscFunctionReturn(PETSC_SUCCESS);
9385 }
9386 
9387 /*@
9388   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9389 
9390   Not Collective
9391 
9392   Input Parameter:
9393 . A - the matrix to check
9394 
9395   Output Parameters:
9396 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9397 - flg - the result (only valid if set is PETSC_TRUE)
9398 
9399   Level: advanced
9400 
9401   Notes:
9402   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
9403   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9404 
9405   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9406 
9407 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9408 @*/
9409 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9410 {
9411   PetscFunctionBegin;
9412   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9413   PetscAssertPointer(set, 2);
9414   PetscAssertPointer(flg, 3);
9415   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9416     *set = PETSC_TRUE;
9417     *flg = PetscBool3ToBool(A->structurally_symmetric);
9418   } else {
9419     *set = PETSC_FALSE;
9420   }
9421   PetscFunctionReturn(PETSC_SUCCESS);
9422 }
9423 
9424 /*@
9425   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9426   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9427 
9428   Not Collective
9429 
9430   Input Parameter:
9431 . mat - the matrix
9432 
9433   Output Parameters:
9434 + nstash    - the size of the stash
9435 . reallocs  - the number of additional mallocs incurred.
9436 . bnstash   - the size of the block stash
9437 - breallocs - the number of additional mallocs incurred.in the block stash
9438 
9439   Level: advanced
9440 
9441 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9442 @*/
9443 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9444 {
9445   PetscFunctionBegin;
9446   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9447   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9448   PetscFunctionReturn(PETSC_SUCCESS);
9449 }
9450 
9451 /*@C
9452   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9453   parallel layout, `PetscLayout` for rows and columns
9454 
9455   Collective
9456 
9457   Input Parameter:
9458 . mat - the matrix
9459 
9460   Output Parameters:
9461 + right - (optional) vector that the matrix can be multiplied against
9462 - left  - (optional) vector that the matrix vector product can be stored in
9463 
9464   Level: advanced
9465 
9466   Notes:
9467   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()`.
9468 
9469   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9470 
9471 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9472 @*/
9473 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9474 {
9475   PetscFunctionBegin;
9476   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9477   PetscValidType(mat, 1);
9478   if (mat->ops->getvecs) {
9479     PetscUseTypeMethod(mat, getvecs, right, left);
9480   } else {
9481     if (right) {
9482       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9483       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9484       PetscCall(VecSetType(*right, mat->defaultvectype));
9485 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9486       if (mat->boundtocpu && mat->bindingpropagates) {
9487         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9488         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9489       }
9490 #endif
9491     }
9492     if (left) {
9493       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9494       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9495       PetscCall(VecSetType(*left, mat->defaultvectype));
9496 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9497       if (mat->boundtocpu && mat->bindingpropagates) {
9498         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9499         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9500       }
9501 #endif
9502     }
9503   }
9504   PetscFunctionReturn(PETSC_SUCCESS);
9505 }
9506 
9507 /*@C
9508   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9509   with default values.
9510 
9511   Not Collective
9512 
9513   Input Parameter:
9514 . info - the `MatFactorInfo` data structure
9515 
9516   Level: developer
9517 
9518   Notes:
9519   The solvers are generally used through the `KSP` and `PC` objects, for example
9520   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9521 
9522   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9523 
9524   Developer Note:
9525   The Fortran interface is not autogenerated as the
9526   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9527 
9528 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9529 @*/
9530 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9531 {
9532   PetscFunctionBegin;
9533   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9534   PetscFunctionReturn(PETSC_SUCCESS);
9535 }
9536 
9537 /*@
9538   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9539 
9540   Collective
9541 
9542   Input Parameters:
9543 + mat - the factored matrix
9544 - is  - the index set defining the Schur indices (0-based)
9545 
9546   Level: advanced
9547 
9548   Notes:
9549   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9550 
9551   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9552 
9553   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9554 
9555 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9556           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9557 @*/
9558 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9559 {
9560   PetscErrorCode (*f)(Mat, IS);
9561 
9562   PetscFunctionBegin;
9563   PetscValidType(mat, 1);
9564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9565   PetscValidType(is, 2);
9566   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9567   PetscCheckSameComm(mat, 1, is, 2);
9568   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9569   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9570   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9571   PetscCall(MatDestroy(&mat->schur));
9572   PetscCall((*f)(mat, is));
9573   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9574   PetscFunctionReturn(PETSC_SUCCESS);
9575 }
9576 
9577 /*@
9578   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9579 
9580   Logically Collective
9581 
9582   Input Parameters:
9583 + F      - the factored matrix obtained by calling `MatGetFactor()`
9584 . S      - location where to return the Schur complement, can be `NULL`
9585 - status - the status of the Schur complement matrix, can be `NULL`
9586 
9587   Level: advanced
9588 
9589   Notes:
9590   You must call `MatFactorSetSchurIS()` before calling this routine.
9591 
9592   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9593 
9594   The routine provides a copy of the Schur matrix stored within the solver data structures.
9595   The caller must destroy the object when it is no longer needed.
9596   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9597 
9598   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)
9599 
9600   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9601 
9602   Developer Note:
9603   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9604   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9605 
9606 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9607 @*/
9608 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9609 {
9610   PetscFunctionBegin;
9611   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9612   if (S) PetscAssertPointer(S, 2);
9613   if (status) PetscAssertPointer(status, 3);
9614   if (S) {
9615     PetscErrorCode (*f)(Mat, Mat *);
9616 
9617     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9618     if (f) {
9619       PetscCall((*f)(F, S));
9620     } else {
9621       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9622     }
9623   }
9624   if (status) *status = F->schur_status;
9625   PetscFunctionReturn(PETSC_SUCCESS);
9626 }
9627 
9628 /*@
9629   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9630 
9631   Logically Collective
9632 
9633   Input Parameters:
9634 + F      - the factored matrix obtained by calling `MatGetFactor()`
9635 . S      - location where to return the Schur complement, can be `NULL`
9636 - status - the status of the Schur complement matrix, can be `NULL`
9637 
9638   Level: advanced
9639 
9640   Notes:
9641   You must call `MatFactorSetSchurIS()` before calling this routine.
9642 
9643   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9644 
9645   The routine returns a the Schur Complement stored within the data structures of the solver.
9646 
9647   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9648 
9649   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9650 
9651   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9652 
9653   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9654 
9655 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9656 @*/
9657 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9658 {
9659   PetscFunctionBegin;
9660   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9661   if (S) {
9662     PetscAssertPointer(S, 2);
9663     *S = F->schur;
9664   }
9665   if (status) {
9666     PetscAssertPointer(status, 3);
9667     *status = F->schur_status;
9668   }
9669   PetscFunctionReturn(PETSC_SUCCESS);
9670 }
9671 
9672 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9673 {
9674   Mat S = F->schur;
9675 
9676   PetscFunctionBegin;
9677   switch (F->schur_status) {
9678   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9679   case MAT_FACTOR_SCHUR_INVERTED:
9680     if (S) {
9681       S->ops->solve             = NULL;
9682       S->ops->matsolve          = NULL;
9683       S->ops->solvetranspose    = NULL;
9684       S->ops->matsolvetranspose = NULL;
9685       S->ops->solveadd          = NULL;
9686       S->ops->solvetransposeadd = NULL;
9687       S->factortype             = MAT_FACTOR_NONE;
9688       PetscCall(PetscFree(S->solvertype));
9689     }
9690   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9691     break;
9692   default:
9693     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9694   }
9695   PetscFunctionReturn(PETSC_SUCCESS);
9696 }
9697 
9698 /*@
9699   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9700 
9701   Logically Collective
9702 
9703   Input Parameters:
9704 + F      - the factored matrix obtained by calling `MatGetFactor()`
9705 . S      - location where the Schur complement is stored
9706 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9707 
9708   Level: advanced
9709 
9710 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9711 @*/
9712 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9713 {
9714   PetscFunctionBegin;
9715   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9716   if (S) {
9717     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9718     *S = NULL;
9719   }
9720   F->schur_status = status;
9721   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9722   PetscFunctionReturn(PETSC_SUCCESS);
9723 }
9724 
9725 /*@
9726   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9727 
9728   Logically Collective
9729 
9730   Input Parameters:
9731 + F   - the factored matrix obtained by calling `MatGetFactor()`
9732 . rhs - location where the right hand side of the Schur complement system is stored
9733 - sol - location where the solution of the Schur complement system has to be returned
9734 
9735   Level: advanced
9736 
9737   Notes:
9738   The sizes of the vectors should match the size of the Schur complement
9739 
9740   Must be called after `MatFactorSetSchurIS()`
9741 
9742 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9743 @*/
9744 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9745 {
9746   PetscFunctionBegin;
9747   PetscValidType(F, 1);
9748   PetscValidType(rhs, 2);
9749   PetscValidType(sol, 3);
9750   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9751   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9752   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9753   PetscCheckSameComm(F, 1, rhs, 2);
9754   PetscCheckSameComm(F, 1, sol, 3);
9755   PetscCall(MatFactorFactorizeSchurComplement(F));
9756   switch (F->schur_status) {
9757   case MAT_FACTOR_SCHUR_FACTORED:
9758     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9759     break;
9760   case MAT_FACTOR_SCHUR_INVERTED:
9761     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9762     break;
9763   default:
9764     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9765   }
9766   PetscFunctionReturn(PETSC_SUCCESS);
9767 }
9768 
9769 /*@
9770   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9771 
9772   Logically Collective
9773 
9774   Input Parameters:
9775 + F   - the factored matrix obtained by calling `MatGetFactor()`
9776 . rhs - location where the right hand side of the Schur complement system is stored
9777 - sol - location where the solution of the Schur complement system has to be returned
9778 
9779   Level: advanced
9780 
9781   Notes:
9782   The sizes of the vectors should match the size of the Schur complement
9783 
9784   Must be called after `MatFactorSetSchurIS()`
9785 
9786 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9787 @*/
9788 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9789 {
9790   PetscFunctionBegin;
9791   PetscValidType(F, 1);
9792   PetscValidType(rhs, 2);
9793   PetscValidType(sol, 3);
9794   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9795   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9796   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9797   PetscCheckSameComm(F, 1, rhs, 2);
9798   PetscCheckSameComm(F, 1, sol, 3);
9799   PetscCall(MatFactorFactorizeSchurComplement(F));
9800   switch (F->schur_status) {
9801   case MAT_FACTOR_SCHUR_FACTORED:
9802     PetscCall(MatSolve(F->schur, rhs, sol));
9803     break;
9804   case MAT_FACTOR_SCHUR_INVERTED:
9805     PetscCall(MatMult(F->schur, rhs, sol));
9806     break;
9807   default:
9808     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9809   }
9810   PetscFunctionReturn(PETSC_SUCCESS);
9811 }
9812 
9813 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9814 #if PetscDefined(HAVE_CUDA)
9815 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9816 #endif
9817 
9818 /* Schur status updated in the interface */
9819 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9820 {
9821   Mat S = F->schur;
9822 
9823   PetscFunctionBegin;
9824   if (S) {
9825     PetscMPIInt size;
9826     PetscBool   isdense, isdensecuda;
9827 
9828     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9829     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9830     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9831     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9832     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9833     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9834     if (isdense) {
9835       PetscCall(MatSeqDenseInvertFactors_Private(S));
9836     } else if (isdensecuda) {
9837 #if defined(PETSC_HAVE_CUDA)
9838       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9839 #endif
9840     }
9841     // HIP??????????????
9842     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9843   }
9844   PetscFunctionReturn(PETSC_SUCCESS);
9845 }
9846 
9847 /*@
9848   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9849 
9850   Logically Collective
9851 
9852   Input Parameter:
9853 . F - the factored matrix obtained by calling `MatGetFactor()`
9854 
9855   Level: advanced
9856 
9857   Notes:
9858   Must be called after `MatFactorSetSchurIS()`.
9859 
9860   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9861 
9862 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9863 @*/
9864 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9865 {
9866   PetscFunctionBegin;
9867   PetscValidType(F, 1);
9868   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9869   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9870   PetscCall(MatFactorFactorizeSchurComplement(F));
9871   PetscCall(MatFactorInvertSchurComplement_Private(F));
9872   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9873   PetscFunctionReturn(PETSC_SUCCESS);
9874 }
9875 
9876 /*@
9877   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9878 
9879   Logically Collective
9880 
9881   Input Parameter:
9882 . F - the factored matrix obtained by calling `MatGetFactor()`
9883 
9884   Level: advanced
9885 
9886   Note:
9887   Must be called after `MatFactorSetSchurIS()`
9888 
9889 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9890 @*/
9891 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9892 {
9893   MatFactorInfo info;
9894 
9895   PetscFunctionBegin;
9896   PetscValidType(F, 1);
9897   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9898   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9899   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9900   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9901   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9902     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9903   } else {
9904     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9905   }
9906   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9907   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9908   PetscFunctionReturn(PETSC_SUCCESS);
9909 }
9910 
9911 /*@
9912   MatPtAP - Creates the matrix product $C = P^T * A * P$
9913 
9914   Neighbor-wise Collective
9915 
9916   Input Parameters:
9917 + A     - the matrix
9918 . P     - the projection matrix
9919 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9920 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9921           if the result is a dense matrix this is irrelevant
9922 
9923   Output Parameter:
9924 . C - the product matrix
9925 
9926   Level: intermediate
9927 
9928   Notes:
9929   C will be created and must be destroyed by the user with `MatDestroy()`.
9930 
9931   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9932 
9933   Developer Note:
9934   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9935 
9936 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9937 @*/
9938 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9939 {
9940   PetscFunctionBegin;
9941   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9942   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9943 
9944   if (scall == MAT_INITIAL_MATRIX) {
9945     PetscCall(MatProductCreate(A, P, NULL, C));
9946     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9947     PetscCall(MatProductSetAlgorithm(*C, "default"));
9948     PetscCall(MatProductSetFill(*C, fill));
9949 
9950     (*C)->product->api_user = PETSC_TRUE;
9951     PetscCall(MatProductSetFromOptions(*C));
9952     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);
9953     PetscCall(MatProductSymbolic(*C));
9954   } else { /* scall == MAT_REUSE_MATRIX */
9955     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9956   }
9957 
9958   PetscCall(MatProductNumeric(*C));
9959   (*C)->symmetric = A->symmetric;
9960   (*C)->spd       = A->spd;
9961   PetscFunctionReturn(PETSC_SUCCESS);
9962 }
9963 
9964 /*@
9965   MatRARt - Creates the matrix product $C = R * A * R^T$
9966 
9967   Neighbor-wise Collective
9968 
9969   Input Parameters:
9970 + A     - the matrix
9971 . R     - the projection matrix
9972 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9973 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9974           if the result is a dense matrix this is irrelevant
9975 
9976   Output Parameter:
9977 . C - the product matrix
9978 
9979   Level: intermediate
9980 
9981   Notes:
9982   C will be created and must be destroyed by the user with `MatDestroy()`.
9983 
9984   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9985 
9986   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9987   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9988   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9989   We recommend using MatPtAP().
9990 
9991 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9992 @*/
9993 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9994 {
9995   PetscFunctionBegin;
9996   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9997   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9998 
9999   if (scall == MAT_INITIAL_MATRIX) {
10000     PetscCall(MatProductCreate(A, R, NULL, C));
10001     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10002     PetscCall(MatProductSetAlgorithm(*C, "default"));
10003     PetscCall(MatProductSetFill(*C, fill));
10004 
10005     (*C)->product->api_user = PETSC_TRUE;
10006     PetscCall(MatProductSetFromOptions(*C));
10007     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);
10008     PetscCall(MatProductSymbolic(*C));
10009   } else { /* scall == MAT_REUSE_MATRIX */
10010     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10011   }
10012 
10013   PetscCall(MatProductNumeric(*C));
10014   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10015   PetscFunctionReturn(PETSC_SUCCESS);
10016 }
10017 
10018 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10019 {
10020   PetscFunctionBegin;
10021   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10022 
10023   if (scall == MAT_INITIAL_MATRIX) {
10024     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10025     PetscCall(MatProductCreate(A, B, NULL, C));
10026     PetscCall(MatProductSetType(*C, ptype));
10027     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10028     PetscCall(MatProductSetFill(*C, fill));
10029 
10030     (*C)->product->api_user = PETSC_TRUE;
10031     PetscCall(MatProductSetFromOptions(*C));
10032     PetscCall(MatProductSymbolic(*C));
10033   } else { /* scall == MAT_REUSE_MATRIX */
10034     Mat_Product *product = (*C)->product;
10035     PetscBool    isdense;
10036 
10037     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10038     if (isdense && product && product->type != ptype) {
10039       PetscCall(MatProductClear(*C));
10040       product = NULL;
10041     }
10042     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10043     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10044       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10045       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10046       product           = (*C)->product;
10047       product->fill     = fill;
10048       product->api_user = PETSC_TRUE;
10049       product->clear    = PETSC_TRUE;
10050 
10051       PetscCall(MatProductSetType(*C, ptype));
10052       PetscCall(MatProductSetFromOptions(*C));
10053       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);
10054       PetscCall(MatProductSymbolic(*C));
10055     } else { /* user may change input matrices A or B when REUSE */
10056       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10057     }
10058   }
10059   PetscCall(MatProductNumeric(*C));
10060   PetscFunctionReturn(PETSC_SUCCESS);
10061 }
10062 
10063 /*@
10064   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10065 
10066   Neighbor-wise Collective
10067 
10068   Input Parameters:
10069 + A     - the left matrix
10070 . B     - the right matrix
10071 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10072 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10073           if the result is a dense matrix this is irrelevant
10074 
10075   Output Parameter:
10076 . C - the product matrix
10077 
10078   Notes:
10079   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10080 
10081   `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
10082   call to this function with `MAT_INITIAL_MATRIX`.
10083 
10084   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10085 
10086   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`,
10087   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10088 
10089   Example of Usage:
10090 .vb
10091      MatProductCreate(A,B,NULL,&C);
10092      MatProductSetType(C,MATPRODUCT_AB);
10093      MatProductSymbolic(C);
10094      MatProductNumeric(C); // compute C=A * B
10095      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10096      MatProductNumeric(C);
10097      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10098      MatProductNumeric(C);
10099 .ve
10100 
10101   Level: intermediate
10102 
10103 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10104 @*/
10105 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10106 {
10107   PetscFunctionBegin;
10108   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10109   PetscFunctionReturn(PETSC_SUCCESS);
10110 }
10111 
10112 /*@
10113   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10114 
10115   Neighbor-wise Collective
10116 
10117   Input Parameters:
10118 + A     - the left matrix
10119 . B     - the right matrix
10120 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10121 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10122 
10123   Output Parameter:
10124 . C - the product matrix
10125 
10126   Options Database Key:
10127 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10128               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10129               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10130 
10131   Level: intermediate
10132 
10133   Notes:
10134   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10135 
10136   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10137 
10138   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10139   actually needed.
10140 
10141   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10142   and for pairs of `MATMPIDENSE` matrices.
10143 
10144   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10145 
10146 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10147 @*/
10148 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10149 {
10150   PetscFunctionBegin;
10151   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10152   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10153   PetscFunctionReturn(PETSC_SUCCESS);
10154 }
10155 
10156 /*@
10157   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10158 
10159   Neighbor-wise Collective
10160 
10161   Input Parameters:
10162 + A     - the left matrix
10163 . B     - the right matrix
10164 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10165 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10166 
10167   Output Parameter:
10168 . C - the product matrix
10169 
10170   Level: intermediate
10171 
10172   Notes:
10173   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10174 
10175   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10176 
10177   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10178 
10179   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10180   actually needed.
10181 
10182   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10183   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10184 
10185 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10186 @*/
10187 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10188 {
10189   PetscFunctionBegin;
10190   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10191   PetscFunctionReturn(PETSC_SUCCESS);
10192 }
10193 
10194 /*@
10195   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10196 
10197   Neighbor-wise Collective
10198 
10199   Input Parameters:
10200 + A     - the left matrix
10201 . B     - the middle matrix
10202 . C     - the right matrix
10203 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10204 - 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
10205           if the result is a dense matrix this is irrelevant
10206 
10207   Output Parameter:
10208 . D - the product matrix
10209 
10210   Level: intermediate
10211 
10212   Notes:
10213   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10214 
10215   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10216 
10217   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10218 
10219   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10220   actually needed.
10221 
10222   If you have many matrices with the same non-zero structure to multiply, you
10223   should use `MAT_REUSE_MATRIX` in all calls but the first
10224 
10225 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10226 @*/
10227 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10228 {
10229   PetscFunctionBegin;
10230   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10231   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10232 
10233   if (scall == MAT_INITIAL_MATRIX) {
10234     PetscCall(MatProductCreate(A, B, C, D));
10235     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10236     PetscCall(MatProductSetAlgorithm(*D, "default"));
10237     PetscCall(MatProductSetFill(*D, fill));
10238 
10239     (*D)->product->api_user = PETSC_TRUE;
10240     PetscCall(MatProductSetFromOptions(*D));
10241     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,
10242                ((PetscObject)C)->type_name);
10243     PetscCall(MatProductSymbolic(*D));
10244   } else { /* user may change input matrices when REUSE */
10245     PetscCall(MatProductReplaceMats(A, B, C, *D));
10246   }
10247   PetscCall(MatProductNumeric(*D));
10248   PetscFunctionReturn(PETSC_SUCCESS);
10249 }
10250 
10251 /*@
10252   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10253 
10254   Collective
10255 
10256   Input Parameters:
10257 + mat      - the matrix
10258 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10259 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10260 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10261 
10262   Output Parameter:
10263 . matredundant - redundant matrix
10264 
10265   Level: advanced
10266 
10267   Notes:
10268   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10269   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10270 
10271   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10272   calling it.
10273 
10274   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10275 
10276 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10277 @*/
10278 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10279 {
10280   MPI_Comm       comm;
10281   PetscMPIInt    size;
10282   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10283   Mat_Redundant *redund     = NULL;
10284   PetscSubcomm   psubcomm   = NULL;
10285   MPI_Comm       subcomm_in = subcomm;
10286   Mat           *matseq;
10287   IS             isrow, iscol;
10288   PetscBool      newsubcomm = PETSC_FALSE;
10289 
10290   PetscFunctionBegin;
10291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10292   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10293     PetscAssertPointer(*matredundant, 5);
10294     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10295   }
10296 
10297   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10298   if (size == 1 || nsubcomm == 1) {
10299     if (reuse == MAT_INITIAL_MATRIX) {
10300       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10301     } else {
10302       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");
10303       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10304     }
10305     PetscFunctionReturn(PETSC_SUCCESS);
10306   }
10307 
10308   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10309   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10310   MatCheckPreallocated(mat, 1);
10311 
10312   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10313   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10314     /* create psubcomm, then get subcomm */
10315     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10316     PetscCallMPI(MPI_Comm_size(comm, &size));
10317     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10318 
10319     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10320     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10321     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10322     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10323     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10324     newsubcomm = PETSC_TRUE;
10325     PetscCall(PetscSubcommDestroy(&psubcomm));
10326   }
10327 
10328   /* get isrow, iscol and a local sequential matrix matseq[0] */
10329   if (reuse == MAT_INITIAL_MATRIX) {
10330     mloc_sub = PETSC_DECIDE;
10331     nloc_sub = PETSC_DECIDE;
10332     if (bs < 1) {
10333       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10334       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10335     } else {
10336       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10337       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10338     }
10339     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10340     rstart = rend - mloc_sub;
10341     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10342     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10343     PetscCall(ISSetIdentity(iscol));
10344   } else { /* reuse == MAT_REUSE_MATRIX */
10345     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");
10346     /* retrieve subcomm */
10347     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10348     redund = (*matredundant)->redundant;
10349     isrow  = redund->isrow;
10350     iscol  = redund->iscol;
10351     matseq = redund->matseq;
10352   }
10353   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10354 
10355   /* get matredundant over subcomm */
10356   if (reuse == MAT_INITIAL_MATRIX) {
10357     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10358 
10359     /* create a supporting struct and attach it to C for reuse */
10360     PetscCall(PetscNew(&redund));
10361     (*matredundant)->redundant = redund;
10362     redund->isrow              = isrow;
10363     redund->iscol              = iscol;
10364     redund->matseq             = matseq;
10365     if (newsubcomm) {
10366       redund->subcomm = subcomm;
10367     } else {
10368       redund->subcomm = MPI_COMM_NULL;
10369     }
10370   } else {
10371     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10372   }
10373 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10374   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10375     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10376     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10377   }
10378 #endif
10379   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10380   PetscFunctionReturn(PETSC_SUCCESS);
10381 }
10382 
10383 /*@C
10384   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10385   a given `Mat`. Each submatrix can span multiple procs.
10386 
10387   Collective
10388 
10389   Input Parameters:
10390 + mat     - the matrix
10391 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10392 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10393 
10394   Output Parameter:
10395 . subMat - parallel sub-matrices each spanning a given `subcomm`
10396 
10397   Level: advanced
10398 
10399   Notes:
10400   The submatrix partition across processors is dictated by `subComm` a
10401   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10402   is not restricted to be grouped with consecutive original MPI processes.
10403 
10404   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10405   map directly to the layout of the original matrix [wrt the local
10406   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10407   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10408   the `subMat`. However the offDiagMat looses some columns - and this is
10409   reconstructed with `MatSetValues()`
10410 
10411   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10412 
10413 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10414 @*/
10415 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10416 {
10417   PetscMPIInt commsize, subCommSize;
10418 
10419   PetscFunctionBegin;
10420   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10421   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10422   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10423 
10424   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");
10425   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10426   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10427   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10428   PetscFunctionReturn(PETSC_SUCCESS);
10429 }
10430 
10431 /*@
10432   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10433 
10434   Not Collective
10435 
10436   Input Parameters:
10437 + mat   - matrix to extract local submatrix from
10438 . isrow - local row indices for submatrix
10439 - iscol - local column indices for submatrix
10440 
10441   Output Parameter:
10442 . submat - the submatrix
10443 
10444   Level: intermediate
10445 
10446   Notes:
10447   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10448 
10449   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10450   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10451 
10452   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10453   `MatSetValuesBlockedLocal()` will also be implemented.
10454 
10455   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10456   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10457 
10458 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10459 @*/
10460 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10461 {
10462   PetscFunctionBegin;
10463   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10464   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10465   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10466   PetscCheckSameComm(isrow, 2, iscol, 3);
10467   PetscAssertPointer(submat, 4);
10468   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10469 
10470   if (mat->ops->getlocalsubmatrix) {
10471     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10472   } else {
10473     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10474   }
10475   PetscFunctionReturn(PETSC_SUCCESS);
10476 }
10477 
10478 /*@
10479   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10480 
10481   Not Collective
10482 
10483   Input Parameters:
10484 + mat    - matrix to extract local submatrix from
10485 . isrow  - local row indices for submatrix
10486 . iscol  - local column indices for submatrix
10487 - submat - the submatrix
10488 
10489   Level: intermediate
10490 
10491 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10492 @*/
10493 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10494 {
10495   PetscFunctionBegin;
10496   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10497   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10498   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10499   PetscCheckSameComm(isrow, 2, iscol, 3);
10500   PetscAssertPointer(submat, 4);
10501   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10502 
10503   if (mat->ops->restorelocalsubmatrix) {
10504     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10505   } else {
10506     PetscCall(MatDestroy(submat));
10507   }
10508   *submat = NULL;
10509   PetscFunctionReturn(PETSC_SUCCESS);
10510 }
10511 
10512 /*@
10513   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10514 
10515   Collective
10516 
10517   Input Parameter:
10518 . mat - the matrix
10519 
10520   Output Parameter:
10521 . is - if any rows have zero diagonals this contains the list of them
10522 
10523   Level: developer
10524 
10525 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10526 @*/
10527 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10528 {
10529   PetscFunctionBegin;
10530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10531   PetscValidType(mat, 1);
10532   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10533   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10534 
10535   if (!mat->ops->findzerodiagonals) {
10536     Vec                diag;
10537     const PetscScalar *a;
10538     PetscInt          *rows;
10539     PetscInt           rStart, rEnd, r, nrow = 0;
10540 
10541     PetscCall(MatCreateVecs(mat, &diag, NULL));
10542     PetscCall(MatGetDiagonal(mat, diag));
10543     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10544     PetscCall(VecGetArrayRead(diag, &a));
10545     for (r = 0; r < rEnd - rStart; ++r)
10546       if (a[r] == 0.0) ++nrow;
10547     PetscCall(PetscMalloc1(nrow, &rows));
10548     nrow = 0;
10549     for (r = 0; r < rEnd - rStart; ++r)
10550       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10551     PetscCall(VecRestoreArrayRead(diag, &a));
10552     PetscCall(VecDestroy(&diag));
10553     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10554   } else {
10555     PetscUseTypeMethod(mat, findzerodiagonals, is);
10556   }
10557   PetscFunctionReturn(PETSC_SUCCESS);
10558 }
10559 
10560 /*@
10561   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10562 
10563   Collective
10564 
10565   Input Parameter:
10566 . mat - the matrix
10567 
10568   Output Parameter:
10569 . is - contains the list of rows with off block diagonal entries
10570 
10571   Level: developer
10572 
10573 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10574 @*/
10575 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10576 {
10577   PetscFunctionBegin;
10578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10579   PetscValidType(mat, 1);
10580   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10581   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10582 
10583   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10584   PetscFunctionReturn(PETSC_SUCCESS);
10585 }
10586 
10587 /*@C
10588   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10589 
10590   Collective; No Fortran Support
10591 
10592   Input Parameter:
10593 . mat - the matrix
10594 
10595   Output Parameter:
10596 . values - the block inverses in column major order (FORTRAN-like)
10597 
10598   Level: advanced
10599 
10600   Notes:
10601   The size of the blocks is determined by the block size of the matrix.
10602 
10603   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10604 
10605   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10606 
10607 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10608 @*/
10609 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10610 {
10611   PetscFunctionBegin;
10612   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10613   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10614   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10615   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10616   PetscFunctionReturn(PETSC_SUCCESS);
10617 }
10618 
10619 /*@C
10620   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10621 
10622   Collective; No Fortran Support
10623 
10624   Input Parameters:
10625 + mat     - the matrix
10626 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10627 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10628 
10629   Output Parameter:
10630 . values - the block inverses in column major order (FORTRAN-like)
10631 
10632   Level: advanced
10633 
10634   Notes:
10635   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10636 
10637   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10638 
10639 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10640 @*/
10641 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10642 {
10643   PetscFunctionBegin;
10644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10645   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10646   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10647   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10648   PetscFunctionReturn(PETSC_SUCCESS);
10649 }
10650 
10651 /*@
10652   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10653 
10654   Collective
10655 
10656   Input Parameters:
10657 + A - the matrix
10658 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10659 
10660   Level: advanced
10661 
10662   Note:
10663   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10664 
10665 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10666 @*/
10667 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10668 {
10669   const PetscScalar *vals;
10670   PetscInt          *dnnz;
10671   PetscInt           m, rstart, rend, bs, i, j;
10672 
10673   PetscFunctionBegin;
10674   PetscCall(MatInvertBlockDiagonal(A, &vals));
10675   PetscCall(MatGetBlockSize(A, &bs));
10676   PetscCall(MatGetLocalSize(A, &m, NULL));
10677   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10678   PetscCall(PetscMalloc1(m / bs, &dnnz));
10679   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10680   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10681   PetscCall(PetscFree(dnnz));
10682   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10683   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10684   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10685   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10686   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10687   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10688   PetscFunctionReturn(PETSC_SUCCESS);
10689 }
10690 
10691 /*@C
10692   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10693   via `MatTransposeColoringCreate()`.
10694 
10695   Collective
10696 
10697   Input Parameter:
10698 . c - coloring context
10699 
10700   Level: intermediate
10701 
10702 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10703 @*/
10704 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10705 {
10706   MatTransposeColoring matcolor = *c;
10707 
10708   PetscFunctionBegin;
10709   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10710   if (--((PetscObject)matcolor)->refct > 0) {
10711     matcolor = NULL;
10712     PetscFunctionReturn(PETSC_SUCCESS);
10713   }
10714 
10715   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10716   PetscCall(PetscFree(matcolor->rows));
10717   PetscCall(PetscFree(matcolor->den2sp));
10718   PetscCall(PetscFree(matcolor->colorforcol));
10719   PetscCall(PetscFree(matcolor->columns));
10720   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10721   PetscCall(PetscHeaderDestroy(c));
10722   PetscFunctionReturn(PETSC_SUCCESS);
10723 }
10724 
10725 /*@C
10726   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10727   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10728   `MatTransposeColoring` to sparse `B`.
10729 
10730   Collective
10731 
10732   Input Parameters:
10733 + coloring - coloring context created with `MatTransposeColoringCreate()`
10734 - B        - sparse matrix
10735 
10736   Output Parameter:
10737 . Btdense - dense matrix $B^T$
10738 
10739   Level: developer
10740 
10741   Note:
10742   These are used internally for some implementations of `MatRARt()`
10743 
10744 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10745 @*/
10746 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10747 {
10748   PetscFunctionBegin;
10749   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10750   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10751   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10752 
10753   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10754   PetscFunctionReturn(PETSC_SUCCESS);
10755 }
10756 
10757 /*@C
10758   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10759   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10760   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10761   $C_{sp}$ from $C_{den}$.
10762 
10763   Collective
10764 
10765   Input Parameters:
10766 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10767 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10768 
10769   Output Parameter:
10770 . Csp - sparse matrix
10771 
10772   Level: developer
10773 
10774   Note:
10775   These are used internally for some implementations of `MatRARt()`
10776 
10777 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10778 @*/
10779 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10780 {
10781   PetscFunctionBegin;
10782   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10783   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10784   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10785 
10786   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10787   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10788   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10789   PetscFunctionReturn(PETSC_SUCCESS);
10790 }
10791 
10792 /*@C
10793   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10794 
10795   Collective
10796 
10797   Input Parameters:
10798 + mat        - the matrix product C
10799 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10800 
10801   Output Parameter:
10802 . color - the new coloring context
10803 
10804   Level: intermediate
10805 
10806 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10807           `MatTransColoringApplyDenToSp()`
10808 @*/
10809 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10810 {
10811   MatTransposeColoring c;
10812   MPI_Comm             comm;
10813 
10814   PetscFunctionBegin;
10815   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10816   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10817   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10818 
10819   c->ctype = iscoloring->ctype;
10820   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10821 
10822   *color = c;
10823   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10824   PetscFunctionReturn(PETSC_SUCCESS);
10825 }
10826 
10827 /*@
10828   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10829   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10830   same, otherwise it will be larger
10831 
10832   Not Collective
10833 
10834   Input Parameter:
10835 . mat - the matrix
10836 
10837   Output Parameter:
10838 . state - the current state
10839 
10840   Level: intermediate
10841 
10842   Notes:
10843   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10844   different matrices
10845 
10846   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10847 
10848   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10849 
10850 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10851 @*/
10852 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10853 {
10854   PetscFunctionBegin;
10855   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10856   *state = mat->nonzerostate;
10857   PetscFunctionReturn(PETSC_SUCCESS);
10858 }
10859 
10860 /*@
10861   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10862   matrices from each processor
10863 
10864   Collective
10865 
10866   Input Parameters:
10867 + comm   - the communicators the parallel matrix will live on
10868 . seqmat - the input sequential matrices
10869 . n      - number of local columns (or `PETSC_DECIDE`)
10870 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10871 
10872   Output Parameter:
10873 . mpimat - the parallel matrix generated
10874 
10875   Level: developer
10876 
10877   Note:
10878   The number of columns of the matrix in EACH processor MUST be the same.
10879 
10880 .seealso: [](ch_matrices), `Mat`
10881 @*/
10882 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10883 {
10884   PetscMPIInt size;
10885 
10886   PetscFunctionBegin;
10887   PetscCallMPI(MPI_Comm_size(comm, &size));
10888   if (size == 1) {
10889     if (reuse == MAT_INITIAL_MATRIX) {
10890       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10891     } else {
10892       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10893     }
10894     PetscFunctionReturn(PETSC_SUCCESS);
10895   }
10896 
10897   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");
10898 
10899   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10900   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10901   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10902   PetscFunctionReturn(PETSC_SUCCESS);
10903 }
10904 
10905 /*@
10906   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10907 
10908   Collective
10909 
10910   Input Parameters:
10911 + A - the matrix to create subdomains from
10912 - N - requested number of subdomains
10913 
10914   Output Parameters:
10915 + n   - number of subdomains resulting on this MPI process
10916 - iss - `IS` list with indices of subdomains on this MPI process
10917 
10918   Level: advanced
10919 
10920   Note:
10921   The number of subdomains must be smaller than the communicator size
10922 
10923 .seealso: [](ch_matrices), `Mat`, `IS`
10924 @*/
10925 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10926 {
10927   MPI_Comm    comm, subcomm;
10928   PetscMPIInt size, rank, color;
10929   PetscInt    rstart, rend, k;
10930 
10931   PetscFunctionBegin;
10932   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10933   PetscCallMPI(MPI_Comm_size(comm, &size));
10934   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10935   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);
10936   *n    = 1;
10937   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10938   color = rank / k;
10939   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10940   PetscCall(PetscMalloc1(1, iss));
10941   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10942   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10943   PetscCallMPI(MPI_Comm_free(&subcomm));
10944   PetscFunctionReturn(PETSC_SUCCESS);
10945 }
10946 
10947 /*@
10948   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10949 
10950   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10951   If they are not the same, uses `MatMatMatMult()`.
10952 
10953   Once the coarse grid problem is constructed, correct for interpolation operators
10954   that are not of full rank, which can legitimately happen in the case of non-nested
10955   geometric multigrid.
10956 
10957   Input Parameters:
10958 + restrct     - restriction operator
10959 . dA          - fine grid matrix
10960 . interpolate - interpolation operator
10961 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10962 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10963 
10964   Output Parameter:
10965 . A - the Galerkin coarse matrix
10966 
10967   Options Database Key:
10968 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10969 
10970   Level: developer
10971 
10972 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10973 @*/
10974 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10975 {
10976   IS  zerorows;
10977   Vec diag;
10978 
10979   PetscFunctionBegin;
10980   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10981   /* Construct the coarse grid matrix */
10982   if (interpolate == restrct) {
10983     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10984   } else {
10985     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10986   }
10987 
10988   /* If the interpolation matrix is not of full rank, A will have zero rows.
10989      This can legitimately happen in the case of non-nested geometric multigrid.
10990      In that event, we set the rows of the matrix to the rows of the identity,
10991      ignoring the equations (as the RHS will also be zero). */
10992 
10993   PetscCall(MatFindZeroRows(*A, &zerorows));
10994 
10995   if (zerorows != NULL) { /* if there are any zero rows */
10996     PetscCall(MatCreateVecs(*A, &diag, NULL));
10997     PetscCall(MatGetDiagonal(*A, diag));
10998     PetscCall(VecISSet(diag, zerorows, 1.0));
10999     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11000     PetscCall(VecDestroy(&diag));
11001     PetscCall(ISDestroy(&zerorows));
11002   }
11003   PetscFunctionReturn(PETSC_SUCCESS);
11004 }
11005 
11006 /*@C
11007   MatSetOperation - Allows user to set a matrix operation for any matrix type
11008 
11009   Logically Collective
11010 
11011   Input Parameters:
11012 + mat - the matrix
11013 . op  - the name of the operation
11014 - f   - the function that provides the operation
11015 
11016   Level: developer
11017 
11018   Example Usage:
11019 .vb
11020   extern PetscErrorCode usermult(Mat, Vec, Vec);
11021 
11022   PetscCall(MatCreateXXX(comm, ..., &A));
11023   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11024 .ve
11025 
11026   Notes:
11027   See the file `include/petscmat.h` for a complete list of matrix
11028   operations, which all have the form MATOP_<OPERATION>, where
11029   <OPERATION> is the name (in all capital letters) of the
11030   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11031 
11032   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11033   sequence as the usual matrix interface routines, since they
11034   are intended to be accessed via the usual matrix interface
11035   routines, e.g.,
11036 .vb
11037   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11038 .ve
11039 
11040   In particular each function MUST return `PETSC_SUCCESS` on success and
11041   nonzero on failure.
11042 
11043   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11044 
11045 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11046 @*/
11047 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11048 {
11049   PetscFunctionBegin;
11050   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11051   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11052   (((void (**)(void))mat->ops)[op]) = f;
11053   PetscFunctionReturn(PETSC_SUCCESS);
11054 }
11055 
11056 /*@C
11057   MatGetOperation - Gets a matrix operation for any matrix type.
11058 
11059   Not Collective
11060 
11061   Input Parameters:
11062 + mat - the matrix
11063 - op  - the name of the operation
11064 
11065   Output Parameter:
11066 . f - the function that provides the operation
11067 
11068   Level: developer
11069 
11070   Example Usage:
11071 .vb
11072   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11073 
11074   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11075 .ve
11076 
11077   Notes:
11078   See the file include/petscmat.h for a complete list of matrix
11079   operations, which all have the form MATOP_<OPERATION>, where
11080   <OPERATION> is the name (in all capital letters) of the
11081   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11082 
11083   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11084 
11085 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11086 @*/
11087 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11088 {
11089   PetscFunctionBegin;
11090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11091   *f = (((void (**)(void))mat->ops)[op]);
11092   PetscFunctionReturn(PETSC_SUCCESS);
11093 }
11094 
11095 /*@
11096   MatHasOperation - Determines whether the given matrix supports the particular operation.
11097 
11098   Not Collective
11099 
11100   Input Parameters:
11101 + mat - the matrix
11102 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11103 
11104   Output Parameter:
11105 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11106 
11107   Level: advanced
11108 
11109   Note:
11110   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11111 
11112 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11113 @*/
11114 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11115 {
11116   PetscFunctionBegin;
11117   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11118   PetscAssertPointer(has, 3);
11119   if (mat->ops->hasoperation) {
11120     PetscUseTypeMethod(mat, hasoperation, op, has);
11121   } else {
11122     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11123     else {
11124       *has = PETSC_FALSE;
11125       if (op == MATOP_CREATE_SUBMATRIX) {
11126         PetscMPIInt size;
11127 
11128         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11129         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11130       }
11131     }
11132   }
11133   PetscFunctionReturn(PETSC_SUCCESS);
11134 }
11135 
11136 /*@
11137   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11138 
11139   Collective
11140 
11141   Input Parameter:
11142 . mat - the matrix
11143 
11144   Output Parameter:
11145 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11146 
11147   Level: beginner
11148 
11149 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11150 @*/
11151 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11152 {
11153   PetscFunctionBegin;
11154   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11155   PetscValidType(mat, 1);
11156   PetscAssertPointer(cong, 2);
11157   if (!mat->rmap || !mat->cmap) {
11158     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11159     PetscFunctionReturn(PETSC_SUCCESS);
11160   }
11161   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11162     PetscCall(PetscLayoutSetUp(mat->rmap));
11163     PetscCall(PetscLayoutSetUp(mat->cmap));
11164     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11165     if (*cong) mat->congruentlayouts = 1;
11166     else mat->congruentlayouts = 0;
11167   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11168   PetscFunctionReturn(PETSC_SUCCESS);
11169 }
11170 
11171 PetscErrorCode MatSetInf(Mat A)
11172 {
11173   PetscFunctionBegin;
11174   PetscUseTypeMethod(A, setinf);
11175   PetscFunctionReturn(PETSC_SUCCESS);
11176 }
11177 
11178 /*@C
11179   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
11180   and possibly removes small values from the graph structure.
11181 
11182   Collective
11183 
11184   Input Parameters:
11185 + A       - the matrix
11186 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11187 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11188 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11189 . num_idx - size of 'index' array
11190 - index   - array of block indices to use for graph strength of connection weight
11191 
11192   Output Parameter:
11193 . graph - the resulting graph
11194 
11195   Level: advanced
11196 
11197 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11198 @*/
11199 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11200 {
11201   PetscFunctionBegin;
11202   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11203   PetscValidType(A, 1);
11204   PetscValidLogicalCollectiveBool(A, scale, 3);
11205   PetscAssertPointer(graph, 7);
11206   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11207   PetscFunctionReturn(PETSC_SUCCESS);
11208 }
11209 
11210 /*@
11211   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11212   meaning the same memory is used for the matrix, and no new memory is allocated.
11213 
11214   Collective
11215 
11216   Input Parameters:
11217 + A    - the matrix
11218 - 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
11219 
11220   Level: intermediate
11221 
11222   Developer Note:
11223   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11224   of the arrays in the data structure are unneeded.
11225 
11226 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11227 @*/
11228 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11229 {
11230   PetscFunctionBegin;
11231   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11232   PetscUseTypeMethod(A, eliminatezeros, keep);
11233   PetscFunctionReturn(PETSC_SUCCESS);
11234 }
11235