xref: /petsc/src/mat/interface/matrix.c (revision bd8f7e58be13ae35c57c11fb871ba6aa483dcf68)
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, MAT_HIPCopyToGPU;
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 /*@
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 /*@
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 /*@
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 /*@
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 /*@
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 /*@C
878   MatGetState - Gets the state of a `Mat`.
879 
880   Not Collective
881 
882   Input Parameter:
883 . A - the matrix
884 
885   Output Parameter:
886 . state - the object state
887 
888   Level: advanced
889 
890   Note:
891   Object state is an integer which gets increased every time
892   the object is changed. By saving and later querying the object state
893   one can determine whether information about the object is still current.
894 
895 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`
896 @*/
897 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
898 {
899   PetscFunctionBegin;
900   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
901   PetscAssertPointer(state, 2);
902   PetscCall(PetscObjectStateGet((PetscObject)A, state));
903   PetscFunctionReturn(PETSC_SUCCESS);
904 }
905 
906 /*@
907   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
908 
909   Collective
910 
911   Input Parameter:
912 . A - the matrix
913 
914   Level: beginner
915 
916   Notes:
917   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
918 
919   Users can reset the preallocation to access the original memory.
920 
921   Currently only supported for  `MATAIJ` matrices.
922 
923 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
924 @*/
925 PetscErrorCode MatResetPreallocation(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   PetscValidType(A, 1);
930   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
931   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
932   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
933   PetscFunctionReturn(PETSC_SUCCESS);
934 }
935 
936 /*@
937   MatSetUp - Sets up the internal matrix data structures for later use.
938 
939   Collective
940 
941   Input Parameter:
942 . A - the matrix
943 
944   Level: intermediate
945 
946   Notes:
947   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
948   setting values in the matrix.
949 
950   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
951 
952 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
953 @*/
954 PetscErrorCode MatSetUp(Mat A)
955 {
956   PetscFunctionBegin;
957   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
958   if (!((PetscObject)A)->type_name) {
959     PetscMPIInt size;
960 
961     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
962     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
963   }
964   if (!A->preallocated) PetscTryTypeMethod(A, setup);
965   PetscCall(PetscLayoutSetUp(A->rmap));
966   PetscCall(PetscLayoutSetUp(A->cmap));
967   A->preallocated = PETSC_TRUE;
968   PetscFunctionReturn(PETSC_SUCCESS);
969 }
970 
971 #if defined(PETSC_HAVE_SAWS)
972   #include <petscviewersaws.h>
973 #endif
974 
975 /*
976    If threadsafety is on extraneous matrices may be printed
977 
978    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
979 */
980 #if !defined(PETSC_HAVE_THREADSAFETY)
981 static PetscInt insidematview = 0;
982 #endif
983 
984 /*@
985   MatViewFromOptions - View properties of the matrix based on options set in the options database
986 
987   Collective
988 
989   Input Parameters:
990 + A    - the matrix
991 . obj  - optional additional object that provides the options prefix to use
992 - name - command line option
993 
994   Options Database Key:
995 . -mat_view [viewertype]:... - the viewer and its options
996 
997   Level: intermediate
998 
999   Note:
1000 .vb
1001     If no value is provided ascii:stdout is used
1002        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1003                                                   for example ascii::ascii_info prints just the information about the object not all details
1004                                                   unless :append is given filename opens in write mode, overwriting what was already there
1005        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1006        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1007        socket[:port]                             defaults to the standard output port
1008        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1009 .ve
1010 
1011 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1012 @*/
1013 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1014 {
1015   PetscFunctionBegin;
1016   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1017 #if !defined(PETSC_HAVE_THREADSAFETY)
1018   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1019 #endif
1020   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1021   PetscFunctionReturn(PETSC_SUCCESS);
1022 }
1023 
1024 /*@
1025   MatView - display information about a matrix in a variety ways
1026 
1027   Collective on viewer
1028 
1029   Input Parameters:
1030 + mat    - the matrix
1031 - viewer - visualization context
1032 
1033   Options Database Keys:
1034 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1035 . -mat_view ::ascii_info_detail    - Prints more detailed info
1036 . -mat_view                        - Prints matrix in ASCII format
1037 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1038 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1039 . -display <name>                  - Sets display name (default is host)
1040 . -draw_pause <sec>                - Sets number of seconds to pause after display
1041 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1042 . -viewer_socket_machine <machine> - -
1043 . -viewer_socket_port <port>       - -
1044 . -mat_view binary                 - save matrix to file in binary format
1045 - -viewer_binary_filename <name>   - -
1046 
1047   Level: beginner
1048 
1049   Notes:
1050   The available visualization contexts include
1051 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1052 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1053 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1054 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1055 
1056   The user can open alternative visualization contexts with
1057 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1058 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1059   specified file; corresponding input uses `MatLoad()`
1060 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1061   an X window display
1062 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1063   Currently only the `MATSEQDENSE` and `MATAIJ`
1064   matrix types support the Socket viewer.
1065 
1066   The user can call `PetscViewerPushFormat()` to specify the output
1067   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1068   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1069 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1070 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1071 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1072 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1073   format common among all matrix types
1074 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1075   format (which is in many cases the same as the default)
1076 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1077   size and structure (not the matrix entries)
1078 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1079   the matrix structure
1080 
1081   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1082   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1083 
1084   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1085 
1086   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1087   viewer is used.
1088 
1089   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1090   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1091 
1092   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1093   and then use the following mouse functions.
1094 .vb
1095   left mouse: zoom in
1096   middle mouse: zoom out
1097   right mouse: continue with the simulation
1098 .ve
1099 
1100 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1101           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1102 @*/
1103 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1104 {
1105   PetscInt          rows, cols, rbs, cbs;
1106   PetscBool         isascii, isstring, issaws;
1107   PetscViewerFormat format;
1108   PetscMPIInt       size;
1109 
1110   PetscFunctionBegin;
1111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1112   PetscValidType(mat, 1);
1113   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1114   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1115 
1116   PetscCall(PetscViewerGetFormat(viewer, &format));
1117   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1118   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1119 
1120 #if !defined(PETSC_HAVE_THREADSAFETY)
1121   insidematview++;
1122 #endif
1123   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1124   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1125   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1126   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1127 
1128   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1129   if (isascii) {
1130     if (!mat->preallocated) {
1131       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1132 #if !defined(PETSC_HAVE_THREADSAFETY)
1133       insidematview--;
1134 #endif
1135       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1136       PetscFunctionReturn(PETSC_SUCCESS);
1137     }
1138     if (!mat->assembled) {
1139       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1140 #if !defined(PETSC_HAVE_THREADSAFETY)
1141       insidematview--;
1142 #endif
1143       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1144       PetscFunctionReturn(PETSC_SUCCESS);
1145     }
1146     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1147     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1148       MatNullSpace nullsp, transnullsp;
1149 
1150       PetscCall(PetscViewerASCIIPushTab(viewer));
1151       PetscCall(MatGetSize(mat, &rows, &cols));
1152       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1153       if (rbs != 1 || cbs != 1) {
1154         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : ""));
1155         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1156       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1157       if (mat->factortype) {
1158         MatSolverType solver;
1159         PetscCall(MatFactorGetSolverType(mat, &solver));
1160         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1161       }
1162       if (mat->ops->getinfo) {
1163         MatInfo info;
1164         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1165         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1166         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1167       }
1168       PetscCall(MatGetNullSpace(mat, &nullsp));
1169       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1170       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1171       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1172       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1173       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1174       PetscCall(PetscViewerASCIIPushTab(viewer));
1175       PetscCall(MatProductView(mat, viewer));
1176       PetscCall(PetscViewerASCIIPopTab(viewer));
1177       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1178         IS tmp;
1179 
1180         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1181         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1182         PetscCall(PetscViewerASCIIPushTab(viewer));
1183         PetscCall(ISView(tmp, viewer));
1184         PetscCall(PetscViewerASCIIPopTab(viewer));
1185         PetscCall(ISDestroy(&tmp));
1186       }
1187     }
1188   } else if (issaws) {
1189 #if defined(PETSC_HAVE_SAWS)
1190     PetscMPIInt rank;
1191 
1192     PetscCall(PetscObjectName((PetscObject)mat));
1193     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1194     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1195 #endif
1196   } else if (isstring) {
1197     const char *type;
1198     PetscCall(MatGetType(mat, &type));
1199     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1200     PetscTryTypeMethod(mat, view, viewer);
1201   }
1202   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1203     PetscCall(PetscViewerASCIIPushTab(viewer));
1204     PetscUseTypeMethod(mat, viewnative, viewer);
1205     PetscCall(PetscViewerASCIIPopTab(viewer));
1206   } else if (mat->ops->view) {
1207     PetscCall(PetscViewerASCIIPushTab(viewer));
1208     PetscUseTypeMethod(mat, view, viewer);
1209     PetscCall(PetscViewerASCIIPopTab(viewer));
1210   }
1211   if (isascii) {
1212     PetscCall(PetscViewerGetFormat(viewer, &format));
1213     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1214   }
1215   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1216 #if !defined(PETSC_HAVE_THREADSAFETY)
1217   insidematview--;
1218 #endif
1219   PetscFunctionReturn(PETSC_SUCCESS);
1220 }
1221 
1222 #if defined(PETSC_USE_DEBUG)
1223   #include <../src/sys/totalview/tv_data_display.h>
1224 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1225 {
1226   TV_add_row("Local rows", "int", &mat->rmap->n);
1227   TV_add_row("Local columns", "int", &mat->cmap->n);
1228   TV_add_row("Global rows", "int", &mat->rmap->N);
1229   TV_add_row("Global columns", "int", &mat->cmap->N);
1230   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1231   return TV_format_OK;
1232 }
1233 #endif
1234 
1235 /*@
1236   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1237   with `MatView()`.  The matrix format is determined from the options database.
1238   Generates a parallel MPI matrix if the communicator has more than one
1239   processor.  The default matrix type is `MATAIJ`.
1240 
1241   Collective
1242 
1243   Input Parameters:
1244 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1245             or some related function before a call to `MatLoad()`
1246 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1247 
1248   Options Database Key:
1249 . -matload_block_size <bs> - set block size
1250 
1251   Level: beginner
1252 
1253   Notes:
1254   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1255   `Mat` before calling this routine if you wish to set it from the options database.
1256 
1257   `MatLoad()` automatically loads into the options database any options
1258   given in the file filename.info where filename is the name of the file
1259   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1260   file will be ignored if you use the -viewer_binary_skip_info option.
1261 
1262   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1263   sets the default matrix type AIJ and sets the local and global sizes.
1264   If type and/or size is already set, then the same are used.
1265 
1266   In parallel, each processor can load a subset of rows (or the
1267   entire matrix).  This routine is especially useful when a large
1268   matrix is stored on disk and only part of it is desired on each
1269   processor.  For example, a parallel solver may access only some of
1270   the rows from each processor.  The algorithm used here reads
1271   relatively small blocks of data rather than reading the entire
1272   matrix and then subsetting it.
1273 
1274   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1275   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1276   or the sequence like
1277 .vb
1278     `PetscViewer` v;
1279     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1280     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1281     `PetscViewerSetFromOptions`(v);
1282     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1283     `PetscViewerFileSetName`(v,"datafile");
1284 .ve
1285   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1286 $ -viewer_type {binary, hdf5}
1287 
1288   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1289   and src/mat/tutorials/ex10.c with the second approach.
1290 
1291   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1292   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1293   Multiple objects, both matrices and vectors, can be stored within the same file.
1294   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1295 
1296   Most users should not need to know the details of the binary storage
1297   format, since `MatLoad()` and `MatView()` completely hide these details.
1298   But for anyone who is interested, the standard binary matrix storage
1299   format is
1300 
1301 .vb
1302     PetscInt    MAT_FILE_CLASSID
1303     PetscInt    number of rows
1304     PetscInt    number of columns
1305     PetscInt    total number of nonzeros
1306     PetscInt    *number nonzeros in each row
1307     PetscInt    *column indices of all nonzeros (starting index is zero)
1308     PetscScalar *values of all nonzeros
1309 .ve
1310   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1311   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
1312   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1313 
1314   PETSc automatically does the byte swapping for
1315   machines that store the bytes reversed. Thus if you write your own binary
1316   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1317   and `PetscBinaryWrite()` to see how this may be done.
1318 
1319   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1320   Each processor's chunk is loaded independently by its owning MPI process.
1321   Multiple objects, both matrices and vectors, can be stored within the same file.
1322   They are looked up by their PetscObject name.
1323 
1324   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1325   by default the same structure and naming of the AIJ arrays and column count
1326   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1327 $    save example.mat A b -v7.3
1328   can be directly read by this routine (see Reference 1 for details).
1329 
1330   Depending on your MATLAB version, this format might be a default,
1331   otherwise you can set it as default in Preferences.
1332 
1333   Unless -nocompression flag is used to save the file in MATLAB,
1334   PETSc must be configured with ZLIB package.
1335 
1336   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1337 
1338   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1339 
1340   Corresponding `MatView()` is not yet implemented.
1341 
1342   The loaded matrix is actually a transpose of the original one in MATLAB,
1343   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1344   With this format, matrix is automatically transposed by PETSc,
1345   unless the matrix is marked as SPD or symmetric
1346   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1347 
1348   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1349 
1350 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1351  @*/
1352 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1353 {
1354   PetscBool flg;
1355 
1356   PetscFunctionBegin;
1357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1358   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1359 
1360   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1361 
1362   flg = PETSC_FALSE;
1363   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1364   if (flg) {
1365     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1366     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1367   }
1368   flg = PETSC_FALSE;
1369   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1370   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1371 
1372   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1373   PetscUseTypeMethod(mat, load, viewer);
1374   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1375   PetscFunctionReturn(PETSC_SUCCESS);
1376 }
1377 
1378 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1379 {
1380   Mat_Redundant *redund = *redundant;
1381 
1382   PetscFunctionBegin;
1383   if (redund) {
1384     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1385       PetscCall(ISDestroy(&redund->isrow));
1386       PetscCall(ISDestroy(&redund->iscol));
1387       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1388     } else {
1389       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1390       PetscCall(PetscFree(redund->sbuf_j));
1391       PetscCall(PetscFree(redund->sbuf_a));
1392       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1393         PetscCall(PetscFree(redund->rbuf_j[i]));
1394         PetscCall(PetscFree(redund->rbuf_a[i]));
1395       }
1396       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1397     }
1398 
1399     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1400     PetscCall(PetscFree(redund));
1401   }
1402   PetscFunctionReturn(PETSC_SUCCESS);
1403 }
1404 
1405 /*@C
1406   MatDestroy - Frees space taken by a matrix.
1407 
1408   Collective
1409 
1410   Input Parameter:
1411 . A - the matrix
1412 
1413   Level: beginner
1414 
1415   Developer Note:
1416   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1417   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1418   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1419   if changes are needed here.
1420 
1421 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1422 @*/
1423 PetscErrorCode MatDestroy(Mat *A)
1424 {
1425   PetscFunctionBegin;
1426   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1427   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1428   if (--((PetscObject)*A)->refct > 0) {
1429     *A = NULL;
1430     PetscFunctionReturn(PETSC_SUCCESS);
1431   }
1432 
1433   /* if memory was published with SAWs then destroy it */
1434   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1435   PetscTryTypeMethod(*A, destroy);
1436 
1437   PetscCall(PetscFree((*A)->factorprefix));
1438   PetscCall(PetscFree((*A)->defaultvectype));
1439   PetscCall(PetscFree((*A)->defaultrandtype));
1440   PetscCall(PetscFree((*A)->bsizes));
1441   PetscCall(PetscFree((*A)->solvertype));
1442   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1443   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1444   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1445   PetscCall(MatProductClear(*A));
1446   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1447   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1448   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1449   PetscCall(MatDestroy(&(*A)->schur));
1450   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1451   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1452   PetscCall(PetscHeaderDestroy(A));
1453   PetscFunctionReturn(PETSC_SUCCESS);
1454 }
1455 
1456 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1457 /*@C
1458   MatSetValues - Inserts or adds a block of values into a matrix.
1459   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1460   MUST be called after all calls to `MatSetValues()` have been completed.
1461 
1462   Not Collective
1463 
1464   Input Parameters:
1465 + mat  - the matrix
1466 . v    - a logically two-dimensional array of values
1467 . m    - the number of rows
1468 . idxm - the global indices of the rows
1469 . n    - the number of columns
1470 . idxn - the global indices of the columns
1471 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1472 
1473   Level: beginner
1474 
1475   Notes:
1476   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1477 
1478   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1479   options cannot be mixed without intervening calls to the assembly
1480   routines.
1481 
1482   `MatSetValues()` uses 0-based row and column numbers in Fortran
1483   as well as in C.
1484 
1485   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1486   simply ignored. This allows easily inserting element stiffness matrices
1487   with homogeneous Dirichlet boundary conditions that you don't want represented
1488   in the matrix.
1489 
1490   Efficiency Alert:
1491   The routine `MatSetValuesBlocked()` may offer much better efficiency
1492   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1493 
1494   Developer Note:
1495   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1496   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1497 
1498 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1499           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1500 @*/
1501 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1502 {
1503   PetscFunctionBeginHot;
1504   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1505   PetscValidType(mat, 1);
1506   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1507   PetscAssertPointer(idxm, 3);
1508   PetscAssertPointer(idxn, 5);
1509   MatCheckPreallocated(mat, 1);
1510 
1511   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1512   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1513 
1514   if (PetscDefined(USE_DEBUG)) {
1515     PetscInt i, j;
1516 
1517     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1518     if (v) {
1519       for (i = 0; i < m; i++) {
1520         for (j = 0; j < n; j++) {
1521           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1522 #if defined(PETSC_USE_COMPLEX)
1523             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]);
1524 #else
1525             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]);
1526 #endif
1527         }
1528       }
1529     }
1530     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);
1531     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);
1532   }
1533 
1534   if (mat->assembled) {
1535     mat->was_assembled = PETSC_TRUE;
1536     mat->assembled     = PETSC_FALSE;
1537   }
1538   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1539   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1540   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1541   PetscFunctionReturn(PETSC_SUCCESS);
1542 }
1543 
1544 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1545 /*@
1546   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1547   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1548   MUST be called after all calls to `MatSetValues()` have been completed.
1549 
1550   Not Collective
1551 
1552   Input Parameters:
1553 + mat  - the matrix
1554 . v    - a logically two-dimensional array of values
1555 . ism  - the rows to provide
1556 . isn  - the columns to provide
1557 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1558 
1559   Level: beginner
1560 
1561   Notes:
1562   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1563 
1564   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1565   options cannot be mixed without intervening calls to the assembly
1566   routines.
1567 
1568   `MatSetValues()` uses 0-based row and column numbers in Fortran
1569   as well as in C.
1570 
1571   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1572   simply ignored. This allows easily inserting element stiffness matrices
1573   with homogeneous Dirichlet boundary conditions that you don't want represented
1574   in the matrix.
1575 
1576   Efficiency Alert:
1577   The routine `MatSetValuesBlocked()` may offer much better efficiency
1578   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1579 
1580   This is currently not optimized for any particular `ISType`
1581 
1582   Developer Note:
1583   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1584   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1585 
1586 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1587           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1588 @*/
1589 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1590 {
1591   PetscInt        m, n;
1592   const PetscInt *rows, *cols;
1593 
1594   PetscFunctionBeginHot;
1595   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1596   PetscCall(ISGetIndices(ism, &rows));
1597   PetscCall(ISGetIndices(isn, &cols));
1598   PetscCall(ISGetLocalSize(ism, &m));
1599   PetscCall(ISGetLocalSize(isn, &n));
1600   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1601   PetscCall(ISRestoreIndices(ism, &rows));
1602   PetscCall(ISRestoreIndices(isn, &cols));
1603   PetscFunctionReturn(PETSC_SUCCESS);
1604 }
1605 
1606 /*@
1607   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1608   values into a matrix
1609 
1610   Not Collective
1611 
1612   Input Parameters:
1613 + mat - the matrix
1614 . row - the (block) row to set
1615 - v   - a logically two-dimensional array of values
1616 
1617   Level: intermediate
1618 
1619   Notes:
1620   The values, `v`, are column-oriented (for the block version) and sorted
1621 
1622   All the nonzero values in `row` must be provided
1623 
1624   The matrix must have previously had its column indices set, likely by having been assembled.
1625 
1626   `row` must belong to this MPI process
1627 
1628 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1629           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1630 @*/
1631 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1632 {
1633   PetscInt globalrow;
1634 
1635   PetscFunctionBegin;
1636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1637   PetscValidType(mat, 1);
1638   PetscAssertPointer(v, 3);
1639   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1640   PetscCall(MatSetValuesRow(mat, globalrow, v));
1641   PetscFunctionReturn(PETSC_SUCCESS);
1642 }
1643 
1644 /*@
1645   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1646   values into a matrix
1647 
1648   Not Collective
1649 
1650   Input Parameters:
1651 + mat - the matrix
1652 . row - the (block) row to set
1653 - 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
1654 
1655   Level: advanced
1656 
1657   Notes:
1658   The values, `v`, are column-oriented for the block version.
1659 
1660   All the nonzeros in `row` must be provided
1661 
1662   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1663 
1664   `row` must belong to this process
1665 
1666 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1667           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1668 @*/
1669 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1670 {
1671   PetscFunctionBeginHot;
1672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1673   PetscValidType(mat, 1);
1674   MatCheckPreallocated(mat, 1);
1675   PetscAssertPointer(v, 3);
1676   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1677   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1678   mat->insertmode = INSERT_VALUES;
1679 
1680   if (mat->assembled) {
1681     mat->was_assembled = PETSC_TRUE;
1682     mat->assembled     = PETSC_FALSE;
1683   }
1684   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1685   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1686   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1687   PetscFunctionReturn(PETSC_SUCCESS);
1688 }
1689 
1690 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1691 /*@
1692   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1693   Using structured grid indexing
1694 
1695   Not Collective
1696 
1697   Input Parameters:
1698 + mat  - the matrix
1699 . m    - number of rows being entered
1700 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1701 . n    - number of columns being entered
1702 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1703 . v    - a logically two-dimensional array of values
1704 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1705 
1706   Level: beginner
1707 
1708   Notes:
1709   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1710 
1711   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1712   options cannot be mixed without intervening calls to the assembly
1713   routines.
1714 
1715   The grid coordinates are across the entire grid, not just the local portion
1716 
1717   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1718   as well as in C.
1719 
1720   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1721 
1722   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1723   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1724 
1725   The columns and rows in the stencil passed in MUST be contained within the
1726   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1727   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1728   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1729   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1730 
1731   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1732   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1733   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1734   `DM_BOUNDARY_PERIODIC` boundary type.
1735 
1736   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
1737   a single value per point) you can skip filling those indices.
1738 
1739   Inspired by the structured grid interface to the HYPRE package
1740   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1741 
1742   Efficiency Alert:
1743   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1744   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1745 
1746   Fortran Note:
1747   `idxm` and `idxn` should be declared as
1748 $     MatStencil idxm(4,m),idxn(4,n)
1749   and the values inserted using
1750 .vb
1751     idxm(MatStencil_i,1) = i
1752     idxm(MatStencil_j,1) = j
1753     idxm(MatStencil_k,1) = k
1754     idxm(MatStencil_c,1) = c
1755     etc
1756 .ve
1757 
1758 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1759           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1760 @*/
1761 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1762 {
1763   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1764   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1765   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1766 
1767   PetscFunctionBegin;
1768   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1769   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1770   PetscValidType(mat, 1);
1771   PetscAssertPointer(idxm, 3);
1772   PetscAssertPointer(idxn, 5);
1773 
1774   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1775     jdxm = buf;
1776     jdxn = buf + m;
1777   } else {
1778     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1779     jdxm = bufm;
1780     jdxn = bufn;
1781   }
1782   for (i = 0; i < m; i++) {
1783     for (j = 0; j < 3 - sdim; j++) dxm++;
1784     tmp = *dxm++ - starts[0];
1785     for (j = 0; j < dim - 1; j++) {
1786       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1787       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1788     }
1789     if (mat->stencil.noc) dxm++;
1790     jdxm[i] = tmp;
1791   }
1792   for (i = 0; i < n; i++) {
1793     for (j = 0; j < 3 - sdim; j++) dxn++;
1794     tmp = *dxn++ - starts[0];
1795     for (j = 0; j < dim - 1; j++) {
1796       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1797       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1798     }
1799     if (mat->stencil.noc) dxn++;
1800     jdxn[i] = tmp;
1801   }
1802   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1803   PetscCall(PetscFree2(bufm, bufn));
1804   PetscFunctionReturn(PETSC_SUCCESS);
1805 }
1806 
1807 /*@
1808   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1809   Using structured grid indexing
1810 
1811   Not Collective
1812 
1813   Input Parameters:
1814 + mat  - the matrix
1815 . m    - number of rows being entered
1816 . idxm - grid coordinates for matrix rows being entered
1817 . n    - number of columns being entered
1818 . idxn - grid coordinates for matrix columns being entered
1819 . v    - a logically two-dimensional array of values
1820 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1821 
1822   Level: beginner
1823 
1824   Notes:
1825   By default the values, `v`, are row-oriented and unsorted.
1826   See `MatSetOption()` for other options.
1827 
1828   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1829   options cannot be mixed without intervening calls to the assembly
1830   routines.
1831 
1832   The grid coordinates are across the entire grid, not just the local portion
1833 
1834   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1835   as well as in C.
1836 
1837   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1838 
1839   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1840   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1841 
1842   The columns and rows in the stencil passed in MUST be contained within the
1843   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1844   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1845   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1846   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1847 
1848   Negative indices may be passed in idxm and idxn, these rows and columns are
1849   simply ignored. This allows easily inserting element stiffness matrices
1850   with homogeneous Dirichlet boundary conditions that you don't want represented
1851   in the matrix.
1852 
1853   Inspired by the structured grid interface to the HYPRE package
1854   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1855 
1856   Fortran Note:
1857   `idxm` and `idxn` should be declared as
1858 $     MatStencil idxm(4,m),idxn(4,n)
1859   and the values inserted using
1860 .vb
1861     idxm(MatStencil_i,1) = i
1862     idxm(MatStencil_j,1) = j
1863     idxm(MatStencil_k,1) = k
1864    etc
1865 .ve
1866 
1867 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1868           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1869           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1870 @*/
1871 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1872 {
1873   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1874   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1875   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1876 
1877   PetscFunctionBegin;
1878   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1880   PetscValidType(mat, 1);
1881   PetscAssertPointer(idxm, 3);
1882   PetscAssertPointer(idxn, 5);
1883   PetscAssertPointer(v, 6);
1884 
1885   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1886     jdxm = buf;
1887     jdxn = buf + m;
1888   } else {
1889     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1890     jdxm = bufm;
1891     jdxn = bufn;
1892   }
1893   for (i = 0; i < m; i++) {
1894     for (j = 0; j < 3 - sdim; j++) dxm++;
1895     tmp = *dxm++ - starts[0];
1896     for (j = 0; j < sdim - 1; j++) {
1897       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1898       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1899     }
1900     dxm++;
1901     jdxm[i] = tmp;
1902   }
1903   for (i = 0; i < n; i++) {
1904     for (j = 0; j < 3 - sdim; j++) dxn++;
1905     tmp = *dxn++ - starts[0];
1906     for (j = 0; j < sdim - 1; j++) {
1907       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1908       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1909     }
1910     dxn++;
1911     jdxn[i] = tmp;
1912   }
1913   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1914   PetscCall(PetscFree2(bufm, bufn));
1915   PetscFunctionReturn(PETSC_SUCCESS);
1916 }
1917 
1918 /*@
1919   MatSetStencil - Sets the grid information for setting values into a matrix via
1920   `MatSetValuesStencil()`
1921 
1922   Not Collective
1923 
1924   Input Parameters:
1925 + mat    - the matrix
1926 . dim    - dimension of the grid 1, 2, or 3
1927 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1928 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1929 - dof    - number of degrees of freedom per node
1930 
1931   Level: beginner
1932 
1933   Notes:
1934   Inspired by the structured grid interface to the HYPRE package
1935   (www.llnl.gov/CASC/hyper)
1936 
1937   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1938   user.
1939 
1940 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1941           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1942 @*/
1943 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1944 {
1945   PetscFunctionBegin;
1946   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1947   PetscAssertPointer(dims, 3);
1948   PetscAssertPointer(starts, 4);
1949 
1950   mat->stencil.dim = dim + (dof > 1);
1951   for (PetscInt i = 0; i < dim; i++) {
1952     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1953     mat->stencil.starts[i] = starts[dim - i - 1];
1954   }
1955   mat->stencil.dims[dim]   = dof;
1956   mat->stencil.starts[dim] = 0;
1957   mat->stencil.noc         = (PetscBool)(dof == 1);
1958   PetscFunctionReturn(PETSC_SUCCESS);
1959 }
1960 
1961 /*@C
1962   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1963 
1964   Not Collective
1965 
1966   Input Parameters:
1967 + mat  - the matrix
1968 . v    - a logically two-dimensional array of values
1969 . m    - the number of block rows
1970 . idxm - the global block indices
1971 . n    - the number of block columns
1972 . idxn - the global block indices
1973 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1974 
1975   Level: intermediate
1976 
1977   Notes:
1978   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1979   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1980 
1981   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1982   NOT the total number of rows/columns; for example, if the block size is 2 and
1983   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
1984   The values in `idxm` would be 1 2; that is the first index for each block divided by
1985   the block size.
1986 
1987   You must call `MatSetBlockSize()` when constructing this matrix (before
1988   preallocating it).
1989 
1990   By default the values, `v`, are row-oriented, so the layout of
1991   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1992 
1993   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1994   options cannot be mixed without intervening calls to the assembly
1995   routines.
1996 
1997   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1998   as well as in C.
1999 
2000   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2001   simply ignored. This allows easily inserting element stiffness matrices
2002   with homogeneous Dirichlet boundary conditions that you don't want represented
2003   in the matrix.
2004 
2005   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2006   internal searching must be done to determine where to place the
2007   data in the matrix storage space.  By instead inserting blocks of
2008   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2009   reduced.
2010 
2011   Example:
2012 .vb
2013    Suppose m=n=2 and block size(bs) = 2 The array is
2014 
2015    1  2  | 3  4
2016    5  6  | 7  8
2017    - - - | - - -
2018    9  10 | 11 12
2019    13 14 | 15 16
2020 
2021    v[] should be passed in like
2022    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2023 
2024   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2025    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2026 .ve
2027 
2028 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2029 @*/
2030 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2031 {
2032   PetscFunctionBeginHot;
2033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2034   PetscValidType(mat, 1);
2035   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2036   PetscAssertPointer(idxm, 3);
2037   PetscAssertPointer(idxn, 5);
2038   MatCheckPreallocated(mat, 1);
2039   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2040   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2041   if (PetscDefined(USE_DEBUG)) {
2042     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2043     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2044   }
2045   if (PetscDefined(USE_DEBUG)) {
2046     PetscInt rbs, cbs, M, N, i;
2047     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2048     PetscCall(MatGetSize(mat, &M, &N));
2049     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M);
2050     for (i = 0; i < n; i++)
2051       PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N);
2052   }
2053   if (mat->assembled) {
2054     mat->was_assembled = PETSC_TRUE;
2055     mat->assembled     = PETSC_FALSE;
2056   }
2057   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2058   if (mat->ops->setvaluesblocked) {
2059     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2060   } else {
2061     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2062     PetscInt i, j, bs, cbs;
2063 
2064     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2065     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2066       iidxm = buf;
2067       iidxn = buf + m * bs;
2068     } else {
2069       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2070       iidxm = bufr;
2071       iidxn = bufc;
2072     }
2073     for (i = 0; i < m; i++) {
2074       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2075     }
2076     if (m != n || bs != cbs || idxm != idxn) {
2077       for (i = 0; i < n; i++) {
2078         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2079       }
2080     } else iidxn = iidxm;
2081     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2082     PetscCall(PetscFree2(bufr, bufc));
2083   }
2084   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2085   PetscFunctionReturn(PETSC_SUCCESS);
2086 }
2087 
2088 /*@C
2089   MatGetValues - Gets a block of local values from a matrix.
2090 
2091   Not Collective; can only return values that are owned by the give process
2092 
2093   Input Parameters:
2094 + mat  - the matrix
2095 . v    - a logically two-dimensional array for storing the values
2096 . m    - the number of rows
2097 . idxm - the  global indices of the rows
2098 . n    - the number of columns
2099 - idxn - the global indices of the columns
2100 
2101   Level: advanced
2102 
2103   Notes:
2104   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2105   The values, `v`, are then returned in a row-oriented format,
2106   analogous to that used by default in `MatSetValues()`.
2107 
2108   `MatGetValues()` uses 0-based row and column numbers in
2109   Fortran as well as in C.
2110 
2111   `MatGetValues()` requires that the matrix has been assembled
2112   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2113   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2114   without intermediate matrix assembly.
2115 
2116   Negative row or column indices will be ignored and those locations in `v` will be
2117   left unchanged.
2118 
2119   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2120   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2121   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2122 
2123 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2124 @*/
2125 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2126 {
2127   PetscFunctionBegin;
2128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2129   PetscValidType(mat, 1);
2130   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2131   PetscAssertPointer(idxm, 3);
2132   PetscAssertPointer(idxn, 5);
2133   PetscAssertPointer(v, 6);
2134   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2135   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2136   MatCheckPreallocated(mat, 1);
2137 
2138   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2139   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2140   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2141   PetscFunctionReturn(PETSC_SUCCESS);
2142 }
2143 
2144 /*@C
2145   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2146   defined previously by `MatSetLocalToGlobalMapping()`
2147 
2148   Not Collective
2149 
2150   Input Parameters:
2151 + mat  - the matrix
2152 . nrow - number of rows
2153 . irow - the row local indices
2154 . ncol - number of columns
2155 - icol - the column local indices
2156 
2157   Output Parameter:
2158 . y - a logically two-dimensional array of values
2159 
2160   Level: advanced
2161 
2162   Notes:
2163   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2164 
2165   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,
2166   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2167   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2168   with `MatSetLocalToGlobalMapping()`.
2169 
2170   Developer Note:
2171   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2172   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2173 
2174 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2175           `MatSetValuesLocal()`, `MatGetValues()`
2176 @*/
2177 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2178 {
2179   PetscFunctionBeginHot;
2180   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2181   PetscValidType(mat, 1);
2182   MatCheckPreallocated(mat, 1);
2183   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2184   PetscAssertPointer(irow, 3);
2185   PetscAssertPointer(icol, 5);
2186   if (PetscDefined(USE_DEBUG)) {
2187     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2188     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2189   }
2190   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2191   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2192   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2193   else {
2194     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2195     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2196       irowm = buf;
2197       icolm = buf + nrow;
2198     } else {
2199       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2200       irowm = bufr;
2201       icolm = bufc;
2202     }
2203     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2204     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2205     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2206     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2207     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2208     PetscCall(PetscFree2(bufr, bufc));
2209   }
2210   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2211   PetscFunctionReturn(PETSC_SUCCESS);
2212 }
2213 
2214 /*@
2215   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2216   the same size. Currently, this can only be called once and creates the given matrix.
2217 
2218   Not Collective
2219 
2220   Input Parameters:
2221 + mat  - the matrix
2222 . nb   - the number of blocks
2223 . bs   - the number of rows (and columns) in each block
2224 . rows - a concatenation of the rows for each block
2225 - v    - a concatenation of logically two-dimensional arrays of values
2226 
2227   Level: advanced
2228 
2229   Notes:
2230   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2231 
2232   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2233 
2234 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2235           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2236 @*/
2237 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2238 {
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2241   PetscValidType(mat, 1);
2242   PetscAssertPointer(rows, 4);
2243   PetscAssertPointer(v, 5);
2244   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2245 
2246   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2247   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2248   else {
2249     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2250   }
2251   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2252   PetscFunctionReturn(PETSC_SUCCESS);
2253 }
2254 
2255 /*@
2256   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2257   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2258   using a local (per-processor) numbering.
2259 
2260   Not Collective
2261 
2262   Input Parameters:
2263 + x        - the matrix
2264 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2265 - cmapping - column mapping
2266 
2267   Level: intermediate
2268 
2269   Note:
2270   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2271 
2272 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2273 @*/
2274 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2275 {
2276   PetscFunctionBegin;
2277   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2278   PetscValidType(x, 1);
2279   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2280   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2281   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2282   else {
2283     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2284     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2285   }
2286   PetscFunctionReturn(PETSC_SUCCESS);
2287 }
2288 
2289 /*@
2290   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2291 
2292   Not Collective
2293 
2294   Input Parameter:
2295 . A - the matrix
2296 
2297   Output Parameters:
2298 + rmapping - row mapping
2299 - cmapping - column mapping
2300 
2301   Level: advanced
2302 
2303 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2304 @*/
2305 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2306 {
2307   PetscFunctionBegin;
2308   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2309   PetscValidType(A, 1);
2310   if (rmapping) {
2311     PetscAssertPointer(rmapping, 2);
2312     *rmapping = A->rmap->mapping;
2313   }
2314   if (cmapping) {
2315     PetscAssertPointer(cmapping, 3);
2316     *cmapping = A->cmap->mapping;
2317   }
2318   PetscFunctionReturn(PETSC_SUCCESS);
2319 }
2320 
2321 /*@
2322   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2323 
2324   Logically Collective
2325 
2326   Input Parameters:
2327 + A    - the matrix
2328 . rmap - row layout
2329 - cmap - column layout
2330 
2331   Level: advanced
2332 
2333   Note:
2334   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2335 
2336 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2337 @*/
2338 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2339 {
2340   PetscFunctionBegin;
2341   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2342   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2343   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2344   PetscFunctionReturn(PETSC_SUCCESS);
2345 }
2346 
2347 /*@
2348   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2349 
2350   Not Collective
2351 
2352   Input Parameter:
2353 . A - the matrix
2354 
2355   Output Parameters:
2356 + rmap - row layout
2357 - cmap - column layout
2358 
2359   Level: advanced
2360 
2361 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2362 @*/
2363 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2364 {
2365   PetscFunctionBegin;
2366   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2367   PetscValidType(A, 1);
2368   if (rmap) {
2369     PetscAssertPointer(rmap, 2);
2370     *rmap = A->rmap;
2371   }
2372   if (cmap) {
2373     PetscAssertPointer(cmap, 3);
2374     *cmap = A->cmap;
2375   }
2376   PetscFunctionReturn(PETSC_SUCCESS);
2377 }
2378 
2379 /*@C
2380   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2381   using a local numbering of the rows and columns.
2382 
2383   Not Collective
2384 
2385   Input Parameters:
2386 + mat  - the matrix
2387 . nrow - number of rows
2388 . irow - the row local indices
2389 . ncol - number of columns
2390 . icol - the column local indices
2391 . y    - a logically two-dimensional array of values
2392 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2393 
2394   Level: intermediate
2395 
2396   Notes:
2397   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2398 
2399   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2400   options cannot be mixed without intervening calls to the assembly
2401   routines.
2402 
2403   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2404   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2405 
2406   Developer Note:
2407   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2408   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2409 
2410 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2411           `MatGetValuesLocal()`
2412 @*/
2413 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2414 {
2415   PetscFunctionBeginHot;
2416   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2417   PetscValidType(mat, 1);
2418   MatCheckPreallocated(mat, 1);
2419   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2420   PetscAssertPointer(irow, 3);
2421   PetscAssertPointer(icol, 5);
2422   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2423   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2424   if (PetscDefined(USE_DEBUG)) {
2425     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2426     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2427   }
2428 
2429   if (mat->assembled) {
2430     mat->was_assembled = PETSC_TRUE;
2431     mat->assembled     = PETSC_FALSE;
2432   }
2433   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2434   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2435   else {
2436     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2437     const PetscInt *irowm, *icolm;
2438 
2439     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2440       bufr  = buf;
2441       bufc  = buf + nrow;
2442       irowm = bufr;
2443       icolm = bufc;
2444     } else {
2445       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2446       irowm = bufr;
2447       icolm = bufc;
2448     }
2449     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2450     else irowm = irow;
2451     if (mat->cmap->mapping) {
2452       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2453         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2454       } else icolm = irowm;
2455     } else icolm = icol;
2456     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2457     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2458   }
2459   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2460   PetscFunctionReturn(PETSC_SUCCESS);
2461 }
2462 
2463 /*@C
2464   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2465   using a local ordering of the nodes a block at a time.
2466 
2467   Not Collective
2468 
2469   Input Parameters:
2470 + mat  - the matrix
2471 . nrow - number of rows
2472 . irow - the row local indices
2473 . ncol - number of columns
2474 . icol - the column local indices
2475 . y    - a logically two-dimensional array of values
2476 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2477 
2478   Level: intermediate
2479 
2480   Notes:
2481   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2482   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2483 
2484   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2485   options cannot be mixed without intervening calls to the assembly
2486   routines.
2487 
2488   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2489   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2490 
2491   Developer Note:
2492   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2493   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2494 
2495 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2496           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2497 @*/
2498 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2499 {
2500   PetscFunctionBeginHot;
2501   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2502   PetscValidType(mat, 1);
2503   MatCheckPreallocated(mat, 1);
2504   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2505   PetscAssertPointer(irow, 3);
2506   PetscAssertPointer(icol, 5);
2507   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2508   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2509   if (PetscDefined(USE_DEBUG)) {
2510     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2511     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);
2512   }
2513 
2514   if (mat->assembled) {
2515     mat->was_assembled = PETSC_TRUE;
2516     mat->assembled     = PETSC_FALSE;
2517   }
2518   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2519     PetscInt irbs, rbs;
2520     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2521     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2522     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2523   }
2524   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2525     PetscInt icbs, cbs;
2526     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2527     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2528     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2529   }
2530   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2531   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2532   else {
2533     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2534     const PetscInt *irowm, *icolm;
2535 
2536     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2537       bufr  = buf;
2538       bufc  = buf + nrow;
2539       irowm = bufr;
2540       icolm = bufc;
2541     } else {
2542       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2543       irowm = bufr;
2544       icolm = bufc;
2545     }
2546     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2547     else irowm = irow;
2548     if (mat->cmap->mapping) {
2549       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2550         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2551       } else icolm = irowm;
2552     } else icolm = icol;
2553     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2554     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2555   }
2556   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2557   PetscFunctionReturn(PETSC_SUCCESS);
2558 }
2559 
2560 /*@
2561   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2562 
2563   Collective
2564 
2565   Input Parameters:
2566 + mat - the matrix
2567 - x   - the vector to be multiplied
2568 
2569   Output Parameter:
2570 . y - the result
2571 
2572   Level: developer
2573 
2574   Note:
2575   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2576   call `MatMultDiagonalBlock`(A,y,y).
2577 
2578 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2579 @*/
2580 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2581 {
2582   PetscFunctionBegin;
2583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2584   PetscValidType(mat, 1);
2585   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2586   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2587 
2588   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2589   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2590   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2591   MatCheckPreallocated(mat, 1);
2592 
2593   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2594   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2595   PetscFunctionReturn(PETSC_SUCCESS);
2596 }
2597 
2598 /*@
2599   MatMult - Computes the matrix-vector product, $y = Ax$.
2600 
2601   Neighbor-wise Collective
2602 
2603   Input Parameters:
2604 + mat - the matrix
2605 - x   - the vector to be multiplied
2606 
2607   Output Parameter:
2608 . y - the result
2609 
2610   Level: beginner
2611 
2612   Note:
2613   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2614   call `MatMult`(A,y,y).
2615 
2616 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2617 @*/
2618 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2619 {
2620   PetscFunctionBegin;
2621   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2622   PetscValidType(mat, 1);
2623   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2624   VecCheckAssembled(x);
2625   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2626   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2627   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2628   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2629   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);
2630   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);
2631   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);
2632   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);
2633   PetscCall(VecSetErrorIfLocked(y, 3));
2634   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2635   MatCheckPreallocated(mat, 1);
2636 
2637   PetscCall(VecLockReadPush(x));
2638   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2639   PetscUseTypeMethod(mat, mult, x, y);
2640   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2641   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2642   PetscCall(VecLockReadPop(x));
2643   PetscFunctionReturn(PETSC_SUCCESS);
2644 }
2645 
2646 /*@
2647   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2648 
2649   Neighbor-wise Collective
2650 
2651   Input Parameters:
2652 + mat - the matrix
2653 - x   - the vector to be multiplied
2654 
2655   Output Parameter:
2656 . y - the result
2657 
2658   Level: beginner
2659 
2660   Notes:
2661   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2662   call `MatMultTranspose`(A,y,y).
2663 
2664   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2665   use `MatMultHermitianTranspose()`
2666 
2667 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2668 @*/
2669 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2670 {
2671   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2672 
2673   PetscFunctionBegin;
2674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2675   PetscValidType(mat, 1);
2676   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2677   VecCheckAssembled(x);
2678   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2679 
2680   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2681   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2682   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2683   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);
2684   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);
2685   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);
2686   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);
2687   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2688   MatCheckPreallocated(mat, 1);
2689 
2690   if (!mat->ops->multtranspose) {
2691     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2692     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);
2693   } else op = mat->ops->multtranspose;
2694   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2695   PetscCall(VecLockReadPush(x));
2696   PetscCall((*op)(mat, x, y));
2697   PetscCall(VecLockReadPop(x));
2698   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2699   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2700   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2701   PetscFunctionReturn(PETSC_SUCCESS);
2702 }
2703 
2704 /*@
2705   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2706 
2707   Neighbor-wise Collective
2708 
2709   Input Parameters:
2710 + mat - the matrix
2711 - x   - the vector to be multiplied
2712 
2713   Output Parameter:
2714 . y - the result
2715 
2716   Level: beginner
2717 
2718   Notes:
2719   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2720   call `MatMultHermitianTranspose`(A,y,y).
2721 
2722   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2723 
2724   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2725 
2726 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2727 @*/
2728 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2729 {
2730   PetscFunctionBegin;
2731   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2732   PetscValidType(mat, 1);
2733   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2734   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2735 
2736   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2737   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2738   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2739   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);
2740   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);
2741   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);
2742   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);
2743   MatCheckPreallocated(mat, 1);
2744 
2745   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2746 #if defined(PETSC_USE_COMPLEX)
2747   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2748     PetscCall(VecLockReadPush(x));
2749     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2750     else PetscUseTypeMethod(mat, mult, x, y);
2751     PetscCall(VecLockReadPop(x));
2752   } else {
2753     Vec w;
2754     PetscCall(VecDuplicate(x, &w));
2755     PetscCall(VecCopy(x, w));
2756     PetscCall(VecConjugate(w));
2757     PetscCall(MatMultTranspose(mat, w, y));
2758     PetscCall(VecDestroy(&w));
2759     PetscCall(VecConjugate(y));
2760   }
2761   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2762 #else
2763   PetscCall(MatMultTranspose(mat, x, y));
2764 #endif
2765   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2766   PetscFunctionReturn(PETSC_SUCCESS);
2767 }
2768 
2769 /*@
2770   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2771 
2772   Neighbor-wise Collective
2773 
2774   Input Parameters:
2775 + mat - the matrix
2776 . v1  - the vector to be multiplied by `mat`
2777 - v2  - the vector to be added to the result
2778 
2779   Output Parameter:
2780 . v3 - the result
2781 
2782   Level: beginner
2783 
2784   Note:
2785   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2786   call `MatMultAdd`(A,v1,v2,v1).
2787 
2788 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2789 @*/
2790 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2791 {
2792   PetscFunctionBegin;
2793   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2794   PetscValidType(mat, 1);
2795   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2796   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2797   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2798 
2799   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2800   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2801   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);
2802   /* 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);
2803      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); */
2804   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);
2805   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);
2806   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2807   MatCheckPreallocated(mat, 1);
2808 
2809   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2810   PetscCall(VecLockReadPush(v1));
2811   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2812   PetscCall(VecLockReadPop(v1));
2813   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2814   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2815   PetscFunctionReturn(PETSC_SUCCESS);
2816 }
2817 
2818 /*@
2819   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2820 
2821   Neighbor-wise Collective
2822 
2823   Input Parameters:
2824 + mat - the matrix
2825 . v1  - the vector to be multiplied by the transpose of the matrix
2826 - v2  - the vector to be added to the result
2827 
2828   Output Parameter:
2829 . v3 - the result
2830 
2831   Level: beginner
2832 
2833   Note:
2834   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2835   call `MatMultTransposeAdd`(A,v1,v2,v1).
2836 
2837 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2838 @*/
2839 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2840 {
2841   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2842 
2843   PetscFunctionBegin;
2844   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2845   PetscValidType(mat, 1);
2846   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2847   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2848   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2849 
2850   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2851   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2852   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);
2853   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);
2854   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);
2855   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2856   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2857   MatCheckPreallocated(mat, 1);
2858 
2859   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2860   PetscCall(VecLockReadPush(v1));
2861   PetscCall((*op)(mat, v1, v2, v3));
2862   PetscCall(VecLockReadPop(v1));
2863   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2864   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2865   PetscFunctionReturn(PETSC_SUCCESS);
2866 }
2867 
2868 /*@
2869   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2870 
2871   Neighbor-wise Collective
2872 
2873   Input Parameters:
2874 + mat - the matrix
2875 . v1  - the vector to be multiplied by the Hermitian transpose
2876 - v2  - the vector to be added to the result
2877 
2878   Output Parameter:
2879 . v3 - the result
2880 
2881   Level: beginner
2882 
2883   Note:
2884   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2885   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2886 
2887 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2888 @*/
2889 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2890 {
2891   PetscFunctionBegin;
2892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2893   PetscValidType(mat, 1);
2894   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2895   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2896   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2897 
2898   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2899   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2900   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2901   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);
2902   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);
2903   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);
2904   MatCheckPreallocated(mat, 1);
2905 
2906   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2907   PetscCall(VecLockReadPush(v1));
2908   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2909   else {
2910     Vec w, z;
2911     PetscCall(VecDuplicate(v1, &w));
2912     PetscCall(VecCopy(v1, w));
2913     PetscCall(VecConjugate(w));
2914     PetscCall(VecDuplicate(v3, &z));
2915     PetscCall(MatMultTranspose(mat, w, z));
2916     PetscCall(VecDestroy(&w));
2917     PetscCall(VecConjugate(z));
2918     if (v2 != v3) {
2919       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2920     } else {
2921       PetscCall(VecAXPY(v3, 1.0, z));
2922     }
2923     PetscCall(VecDestroy(&z));
2924   }
2925   PetscCall(VecLockReadPop(v1));
2926   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2927   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2928   PetscFunctionReturn(PETSC_SUCCESS);
2929 }
2930 
2931 /*@
2932   MatGetFactorType - gets the type of factorization a matrix is
2933 
2934   Not Collective
2935 
2936   Input Parameter:
2937 . mat - the matrix
2938 
2939   Output Parameter:
2940 . 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`
2941 
2942   Level: intermediate
2943 
2944 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2945           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2946 @*/
2947 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2948 {
2949   PetscFunctionBegin;
2950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2951   PetscValidType(mat, 1);
2952   PetscAssertPointer(t, 2);
2953   *t = mat->factortype;
2954   PetscFunctionReturn(PETSC_SUCCESS);
2955 }
2956 
2957 /*@
2958   MatSetFactorType - sets the type of factorization a matrix is
2959 
2960   Logically Collective
2961 
2962   Input Parameters:
2963 + mat - the matrix
2964 - 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`
2965 
2966   Level: intermediate
2967 
2968 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2969           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2970 @*/
2971 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2972 {
2973   PetscFunctionBegin;
2974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2975   PetscValidType(mat, 1);
2976   mat->factortype = t;
2977   PetscFunctionReturn(PETSC_SUCCESS);
2978 }
2979 
2980 /*@C
2981   MatGetInfo - Returns information about matrix storage (number of
2982   nonzeros, memory, etc.).
2983 
2984   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2985 
2986   Input Parameters:
2987 + mat  - the matrix
2988 - 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)
2989 
2990   Output Parameter:
2991 . info - matrix information context
2992 
2993   Options Database Key:
2994 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2995 
2996   Notes:
2997   The `MatInfo` context contains a variety of matrix data, including
2998   number of nonzeros allocated and used, number of mallocs during
2999   matrix assembly, etc.  Additional information for factored matrices
3000   is provided (such as the fill ratio, number of mallocs during
3001   factorization, etc.).
3002 
3003   Example:
3004   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3005   data within the MatInfo context.  For example,
3006 .vb
3007       MatInfo info;
3008       Mat     A;
3009       double  mal, nz_a, nz_u;
3010 
3011       MatGetInfo(A, MAT_LOCAL, &info);
3012       mal  = info.mallocs;
3013       nz_a = info.nz_allocated;
3014 .ve
3015 
3016   Fortran users should declare info as a double precision
3017   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3018   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3019   a complete list of parameter names.
3020 .vb
3021       double  precision info(MAT_INFO_SIZE)
3022       double  precision mal, nz_a
3023       Mat     A
3024       integer ierr
3025 
3026       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3027       mal = info(MAT_INFO_MALLOCS)
3028       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3029 .ve
3030 
3031   Level: intermediate
3032 
3033   Developer Note:
3034   The Fortran interface is not autogenerated as the
3035   interface definition cannot be generated correctly [due to `MatInfo` argument]
3036 
3037 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3038 @*/
3039 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3040 {
3041   PetscFunctionBegin;
3042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3043   PetscValidType(mat, 1);
3044   PetscAssertPointer(info, 3);
3045   MatCheckPreallocated(mat, 1);
3046   PetscUseTypeMethod(mat, getinfo, flag, info);
3047   PetscFunctionReturn(PETSC_SUCCESS);
3048 }
3049 
3050 /*
3051    This is used by external packages where it is not easy to get the info from the actual
3052    matrix factorization.
3053 */
3054 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3055 {
3056   PetscFunctionBegin;
3057   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3058   PetscFunctionReturn(PETSC_SUCCESS);
3059 }
3060 
3061 /*@C
3062   MatLUFactor - Performs in-place LU factorization of matrix.
3063 
3064   Collective
3065 
3066   Input Parameters:
3067 + mat  - the matrix
3068 . row  - row permutation
3069 . col  - column permutation
3070 - info - options for factorization, includes
3071 .vb
3072           fill - expected fill as ratio of original fill.
3073           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3074                    Run with the option -info to determine an optimal value to use
3075 .ve
3076 
3077   Level: developer
3078 
3079   Notes:
3080   Most users should employ the `KSP` interface for linear solvers
3081   instead of working directly with matrix algebra routines such as this.
3082   See, e.g., `KSPCreate()`.
3083 
3084   This changes the state of the matrix to a factored matrix; it cannot be used
3085   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3086 
3087   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3088   when not using `KSP`.
3089 
3090   Developer Note:
3091   The Fortran interface is not autogenerated as the
3092   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3093 
3094 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3095           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3096 @*/
3097 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3098 {
3099   MatFactorInfo tinfo;
3100 
3101   PetscFunctionBegin;
3102   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3103   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3104   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3105   if (info) PetscAssertPointer(info, 4);
3106   PetscValidType(mat, 1);
3107   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3108   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3109   MatCheckPreallocated(mat, 1);
3110   if (!info) {
3111     PetscCall(MatFactorInfoInitialize(&tinfo));
3112     info = &tinfo;
3113   }
3114 
3115   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3116   PetscUseTypeMethod(mat, lufactor, row, col, info);
3117   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3118   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3119   PetscFunctionReturn(PETSC_SUCCESS);
3120 }
3121 
3122 /*@C
3123   MatILUFactor - Performs in-place ILU factorization of matrix.
3124 
3125   Collective
3126 
3127   Input Parameters:
3128 + mat  - the matrix
3129 . row  - row permutation
3130 . col  - column permutation
3131 - info - structure containing
3132 .vb
3133       levels - number of levels of fill.
3134       expected fill - as ratio of original fill.
3135       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3136                 missing diagonal entries)
3137 .ve
3138 
3139   Level: developer
3140 
3141   Notes:
3142   Most users should employ the `KSP` interface for linear solvers
3143   instead of working directly with matrix algebra routines such as this.
3144   See, e.g., `KSPCreate()`.
3145 
3146   Probably really in-place only when level of fill is zero, otherwise allocates
3147   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3148   when not using `KSP`.
3149 
3150   Developer Note:
3151   The Fortran interface is not autogenerated as the
3152   interface definition cannot be generated correctly [due to MatFactorInfo]
3153 
3154 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3155 @*/
3156 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3157 {
3158   PetscFunctionBegin;
3159   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3160   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3161   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3162   PetscAssertPointer(info, 4);
3163   PetscValidType(mat, 1);
3164   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3165   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3166   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3167   MatCheckPreallocated(mat, 1);
3168 
3169   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3170   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3171   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3172   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3173   PetscFunctionReturn(PETSC_SUCCESS);
3174 }
3175 
3176 /*@C
3177   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3178   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3179 
3180   Collective
3181 
3182   Input Parameters:
3183 + fact - the factor matrix obtained with `MatGetFactor()`
3184 . mat  - the matrix
3185 . row  - the row permutation
3186 . col  - the column permutation
3187 - info - options for factorization, includes
3188 .vb
3189           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3190           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3191 .ve
3192 
3193   Level: developer
3194 
3195   Notes:
3196   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3197 
3198   Most users should employ the simplified `KSP` interface for linear solvers
3199   instead of working directly with matrix algebra routines such as this.
3200   See, e.g., `KSPCreate()`.
3201 
3202   Developer Note:
3203   The Fortran interface is not autogenerated as the
3204   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3205 
3206 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3207 @*/
3208 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3209 {
3210   MatFactorInfo tinfo;
3211 
3212   PetscFunctionBegin;
3213   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3214   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3215   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3216   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3217   if (info) PetscAssertPointer(info, 5);
3218   PetscValidType(fact, 1);
3219   PetscValidType(mat, 2);
3220   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3221   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3222   MatCheckPreallocated(mat, 2);
3223   if (!info) {
3224     PetscCall(MatFactorInfoInitialize(&tinfo));
3225     info = &tinfo;
3226   }
3227 
3228   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3229   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3230   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3231   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3232   PetscFunctionReturn(PETSC_SUCCESS);
3233 }
3234 
3235 /*@C
3236   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3237   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3238 
3239   Collective
3240 
3241   Input Parameters:
3242 + fact - the factor matrix obtained with `MatGetFactor()`
3243 . mat  - the matrix
3244 - info - options for factorization
3245 
3246   Level: developer
3247 
3248   Notes:
3249   See `MatLUFactor()` for in-place factorization.  See
3250   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3251 
3252   Most users should employ the `KSP` interface for linear solvers
3253   instead of working directly with matrix algebra routines such as this.
3254   See, e.g., `KSPCreate()`.
3255 
3256   Developer Note:
3257   The Fortran interface is not autogenerated as the
3258   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3259 
3260 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3261 @*/
3262 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3263 {
3264   MatFactorInfo tinfo;
3265 
3266   PetscFunctionBegin;
3267   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3268   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3269   PetscValidType(fact, 1);
3270   PetscValidType(mat, 2);
3271   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3272   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,
3273              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3274 
3275   MatCheckPreallocated(mat, 2);
3276   if (!info) {
3277     PetscCall(MatFactorInfoInitialize(&tinfo));
3278     info = &tinfo;
3279   }
3280 
3281   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3282   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3283   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3284   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3285   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3286   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3287   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3288   PetscFunctionReturn(PETSC_SUCCESS);
3289 }
3290 
3291 /*@C
3292   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3293   symmetric matrix.
3294 
3295   Collective
3296 
3297   Input Parameters:
3298 + mat  - the matrix
3299 . perm - row and column permutations
3300 - info - expected fill as ratio of original fill
3301 
3302   Level: developer
3303 
3304   Notes:
3305   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3306   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3307 
3308   Most users should employ the `KSP` interface for linear solvers
3309   instead of working directly with matrix algebra routines such as this.
3310   See, e.g., `KSPCreate()`.
3311 
3312   Developer Note:
3313   The Fortran interface is not autogenerated as the
3314   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3315 
3316 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3317           `MatGetOrdering()`
3318 @*/
3319 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3320 {
3321   MatFactorInfo tinfo;
3322 
3323   PetscFunctionBegin;
3324   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3325   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3326   if (info) PetscAssertPointer(info, 3);
3327   PetscValidType(mat, 1);
3328   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3329   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3330   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3331   MatCheckPreallocated(mat, 1);
3332   if (!info) {
3333     PetscCall(MatFactorInfoInitialize(&tinfo));
3334     info = &tinfo;
3335   }
3336 
3337   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3338   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3339   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3340   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3341   PetscFunctionReturn(PETSC_SUCCESS);
3342 }
3343 
3344 /*@C
3345   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3346   of a symmetric matrix.
3347 
3348   Collective
3349 
3350   Input Parameters:
3351 + fact - the factor matrix obtained with `MatGetFactor()`
3352 . mat  - the matrix
3353 . perm - row and column permutations
3354 - info - options for factorization, includes
3355 .vb
3356           fill - expected fill as ratio of original fill.
3357           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3358                    Run with the option -info to determine an optimal value to use
3359 .ve
3360 
3361   Level: developer
3362 
3363   Notes:
3364   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3365   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3366 
3367   Most users should employ the `KSP` interface for linear solvers
3368   instead of working directly with matrix algebra routines such as this.
3369   See, e.g., `KSPCreate()`.
3370 
3371   Developer Note:
3372   The Fortran interface is not autogenerated as the
3373   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3374 
3375 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3376           `MatGetOrdering()`
3377 @*/
3378 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3379 {
3380   MatFactorInfo tinfo;
3381 
3382   PetscFunctionBegin;
3383   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3384   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3385   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3386   if (info) PetscAssertPointer(info, 4);
3387   PetscValidType(fact, 1);
3388   PetscValidType(mat, 2);
3389   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3390   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3391   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3392   MatCheckPreallocated(mat, 2);
3393   if (!info) {
3394     PetscCall(MatFactorInfoInitialize(&tinfo));
3395     info = &tinfo;
3396   }
3397 
3398   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3399   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3400   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3401   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3402   PetscFunctionReturn(PETSC_SUCCESS);
3403 }
3404 
3405 /*@C
3406   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3407   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3408   `MatCholeskyFactorSymbolic()`.
3409 
3410   Collective
3411 
3412   Input Parameters:
3413 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3414 . mat  - the initial matrix that is to be factored
3415 - info - options for factorization
3416 
3417   Level: developer
3418 
3419   Note:
3420   Most users should employ the `KSP` interface for linear solvers
3421   instead of working directly with matrix algebra routines such as this.
3422   See, e.g., `KSPCreate()`.
3423 
3424   Developer Note:
3425   The Fortran interface is not autogenerated as the
3426   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3427 
3428 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3429 @*/
3430 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3431 {
3432   MatFactorInfo tinfo;
3433 
3434   PetscFunctionBegin;
3435   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3437   PetscValidType(fact, 1);
3438   PetscValidType(mat, 2);
3439   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3440   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,
3441              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3442   MatCheckPreallocated(mat, 2);
3443   if (!info) {
3444     PetscCall(MatFactorInfoInitialize(&tinfo));
3445     info = &tinfo;
3446   }
3447 
3448   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3449   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3450   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3451   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3452   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3453   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3454   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3455   PetscFunctionReturn(PETSC_SUCCESS);
3456 }
3457 
3458 /*@
3459   MatQRFactor - Performs in-place QR factorization of matrix.
3460 
3461   Collective
3462 
3463   Input Parameters:
3464 + mat  - the matrix
3465 . col  - column permutation
3466 - info - options for factorization, includes
3467 .vb
3468           fill - expected fill as ratio of original fill.
3469           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3470                    Run with the option -info to determine an optimal value to use
3471 .ve
3472 
3473   Level: developer
3474 
3475   Notes:
3476   Most users should employ the `KSP` interface for linear solvers
3477   instead of working directly with matrix algebra routines such as this.
3478   See, e.g., `KSPCreate()`.
3479 
3480   This changes the state of the matrix to a factored matrix; it cannot be used
3481   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3482 
3483   Developer Note:
3484   The Fortran interface is not autogenerated as the
3485   interface definition cannot be generated correctly [due to MatFactorInfo]
3486 
3487 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3488           `MatSetUnfactored()`
3489 @*/
3490 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3491 {
3492   PetscFunctionBegin;
3493   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3494   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3495   if (info) PetscAssertPointer(info, 3);
3496   PetscValidType(mat, 1);
3497   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3498   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3499   MatCheckPreallocated(mat, 1);
3500   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3501   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3502   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3503   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3504   PetscFunctionReturn(PETSC_SUCCESS);
3505 }
3506 
3507 /*@
3508   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3509   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3510 
3511   Collective
3512 
3513   Input Parameters:
3514 + fact - the factor matrix obtained with `MatGetFactor()`
3515 . mat  - the matrix
3516 . col  - column permutation
3517 - info - options for factorization, includes
3518 .vb
3519           fill - expected fill as ratio of original fill.
3520           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3521                    Run with the option -info to determine an optimal value to use
3522 .ve
3523 
3524   Level: developer
3525 
3526   Note:
3527   Most users should employ the `KSP` interface for linear solvers
3528   instead of working directly with matrix algebra routines such as this.
3529   See, e.g., `KSPCreate()`.
3530 
3531   Developer Note:
3532   The Fortran interface is not autogenerated as the
3533   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3534 
3535 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3536 @*/
3537 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3538 {
3539   MatFactorInfo tinfo;
3540 
3541   PetscFunctionBegin;
3542   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3544   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3545   if (info) PetscAssertPointer(info, 4);
3546   PetscValidType(fact, 1);
3547   PetscValidType(mat, 2);
3548   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3549   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3550   MatCheckPreallocated(mat, 2);
3551   if (!info) {
3552     PetscCall(MatFactorInfoInitialize(&tinfo));
3553     info = &tinfo;
3554   }
3555 
3556   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3557   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3558   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3559   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3560   PetscFunctionReturn(PETSC_SUCCESS);
3561 }
3562 
3563 /*@
3564   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3565   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3566 
3567   Collective
3568 
3569   Input Parameters:
3570 + fact - the factor matrix obtained with `MatGetFactor()`
3571 . mat  - the matrix
3572 - info - options for factorization
3573 
3574   Level: developer
3575 
3576   Notes:
3577   See `MatQRFactor()` for in-place factorization.
3578 
3579   Most users should employ the `KSP` interface for linear solvers
3580   instead of working directly with matrix algebra routines such as this.
3581   See, e.g., `KSPCreate()`.
3582 
3583   Developer Note:
3584   The Fortran interface is not autogenerated as the
3585   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3586 
3587 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3588 @*/
3589 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3590 {
3591   MatFactorInfo tinfo;
3592 
3593   PetscFunctionBegin;
3594   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3595   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3596   PetscValidType(fact, 1);
3597   PetscValidType(mat, 2);
3598   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3599   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,
3600              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3601 
3602   MatCheckPreallocated(mat, 2);
3603   if (!info) {
3604     PetscCall(MatFactorInfoInitialize(&tinfo));
3605     info = &tinfo;
3606   }
3607 
3608   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3609   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3610   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3611   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3612   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3613   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3614   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3615   PetscFunctionReturn(PETSC_SUCCESS);
3616 }
3617 
3618 /*@
3619   MatSolve - Solves $A x = b$, given a factored matrix.
3620 
3621   Neighbor-wise Collective
3622 
3623   Input Parameters:
3624 + mat - the factored matrix
3625 - b   - the right-hand-side vector
3626 
3627   Output Parameter:
3628 . x - the result vector
3629 
3630   Level: developer
3631 
3632   Notes:
3633   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3634   call `MatSolve`(A,x,x).
3635 
3636   Most users should employ the `KSP` interface for linear solvers
3637   instead of working directly with matrix algebra routines such as this.
3638   See, e.g., `KSPCreate()`.
3639 
3640 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3641 @*/
3642 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3643 {
3644   PetscFunctionBegin;
3645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3646   PetscValidType(mat, 1);
3647   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3648   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3649   PetscCheckSameComm(mat, 1, b, 2);
3650   PetscCheckSameComm(mat, 1, x, 3);
3651   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3652   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);
3653   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);
3654   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);
3655   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3656   MatCheckPreallocated(mat, 1);
3657 
3658   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3659   if (mat->factorerrortype) {
3660     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3661     PetscCall(VecSetInf(x));
3662   } else PetscUseTypeMethod(mat, solve, b, x);
3663   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3664   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3665   PetscFunctionReturn(PETSC_SUCCESS);
3666 }
3667 
3668 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3669 {
3670   Vec      b, x;
3671   PetscInt N, i;
3672   PetscErrorCode (*f)(Mat, Vec, Vec);
3673   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3674 
3675   PetscFunctionBegin;
3676   if (A->factorerrortype) {
3677     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3678     PetscCall(MatSetInf(X));
3679     PetscFunctionReturn(PETSC_SUCCESS);
3680   }
3681   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3682   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3683   PetscCall(MatBoundToCPU(A, &Abound));
3684   if (!Abound) {
3685     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3686     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3687   }
3688 #if PetscDefined(HAVE_CUDA)
3689   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3690   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3691 #elif PetscDefined(HAVE_HIP)
3692   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3693   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3694 #endif
3695   PetscCall(MatGetSize(B, NULL, &N));
3696   for (i = 0; i < N; i++) {
3697     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3698     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3699     PetscCall((*f)(A, b, x));
3700     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3701     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3702   }
3703   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3704   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3705   PetscFunctionReturn(PETSC_SUCCESS);
3706 }
3707 
3708 /*@
3709   MatMatSolve - Solves $A X = B$, given a factored matrix.
3710 
3711   Neighbor-wise Collective
3712 
3713   Input Parameters:
3714 + A - the factored matrix
3715 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3716 
3717   Output Parameter:
3718 . X - the result matrix (dense matrix)
3719 
3720   Level: developer
3721 
3722   Note:
3723   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3724   otherwise, `B` and `X` cannot be the same.
3725 
3726 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3727 @*/
3728 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3729 {
3730   PetscFunctionBegin;
3731   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3732   PetscValidType(A, 1);
3733   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3734   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3735   PetscCheckSameComm(A, 1, B, 2);
3736   PetscCheckSameComm(A, 1, X, 3);
3737   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);
3738   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);
3739   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");
3740   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3741   MatCheckPreallocated(A, 1);
3742 
3743   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3744   if (!A->ops->matsolve) {
3745     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3746     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3747   } else PetscUseTypeMethod(A, matsolve, B, X);
3748   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3749   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3750   PetscFunctionReturn(PETSC_SUCCESS);
3751 }
3752 
3753 /*@
3754   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3755 
3756   Neighbor-wise Collective
3757 
3758   Input Parameters:
3759 + A - the factored matrix
3760 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3761 
3762   Output Parameter:
3763 . X - the result matrix (dense matrix)
3764 
3765   Level: developer
3766 
3767   Note:
3768   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3769   call `MatMatSolveTranspose`(A,X,X).
3770 
3771 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3772 @*/
3773 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3774 {
3775   PetscFunctionBegin;
3776   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3777   PetscValidType(A, 1);
3778   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3779   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3780   PetscCheckSameComm(A, 1, B, 2);
3781   PetscCheckSameComm(A, 1, X, 3);
3782   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3783   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);
3784   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);
3785   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);
3786   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");
3787   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3788   MatCheckPreallocated(A, 1);
3789 
3790   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3791   if (!A->ops->matsolvetranspose) {
3792     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3793     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3794   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3795   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3796   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3797   PetscFunctionReturn(PETSC_SUCCESS);
3798 }
3799 
3800 /*@
3801   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3802 
3803   Neighbor-wise Collective
3804 
3805   Input Parameters:
3806 + A  - the factored matrix
3807 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3808 
3809   Output Parameter:
3810 . X - the result matrix (dense matrix)
3811 
3812   Level: developer
3813 
3814   Note:
3815   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
3816   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3817 
3818 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3819 @*/
3820 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3821 {
3822   PetscFunctionBegin;
3823   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3824   PetscValidType(A, 1);
3825   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3826   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3827   PetscCheckSameComm(A, 1, Bt, 2);
3828   PetscCheckSameComm(A, 1, X, 3);
3829 
3830   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3831   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);
3832   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);
3833   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");
3834   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3835   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3836   MatCheckPreallocated(A, 1);
3837 
3838   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3839   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3840   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3841   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3842   PetscFunctionReturn(PETSC_SUCCESS);
3843 }
3844 
3845 /*@
3846   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3847   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3848 
3849   Neighbor-wise Collective
3850 
3851   Input Parameters:
3852 + mat - the factored matrix
3853 - b   - the right-hand-side vector
3854 
3855   Output Parameter:
3856 . x - the result vector
3857 
3858   Level: developer
3859 
3860   Notes:
3861   `MatSolve()` should be used for most applications, as it performs
3862   a forward solve followed by a backward solve.
3863 
3864   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3865   call `MatForwardSolve`(A,x,x).
3866 
3867   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3868   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3869   `MatForwardSolve()` solves $U^T*D y = b$, and
3870   `MatBackwardSolve()` solves $U x = y$.
3871   Thus they do not provide a symmetric preconditioner.
3872 
3873 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3874 @*/
3875 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3876 {
3877   PetscFunctionBegin;
3878   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3879   PetscValidType(mat, 1);
3880   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3881   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3882   PetscCheckSameComm(mat, 1, b, 2);
3883   PetscCheckSameComm(mat, 1, x, 3);
3884   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3885   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);
3886   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);
3887   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);
3888   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3889   MatCheckPreallocated(mat, 1);
3890 
3891   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3892   PetscUseTypeMethod(mat, forwardsolve, b, x);
3893   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3894   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3895   PetscFunctionReturn(PETSC_SUCCESS);
3896 }
3897 
3898 /*@
3899   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3900   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3901 
3902   Neighbor-wise Collective
3903 
3904   Input Parameters:
3905 + mat - the factored matrix
3906 - b   - the right-hand-side vector
3907 
3908   Output Parameter:
3909 . x - the result vector
3910 
3911   Level: developer
3912 
3913   Notes:
3914   `MatSolve()` should be used for most applications, as it performs
3915   a forward solve followed by a backward solve.
3916 
3917   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3918   call `MatBackwardSolve`(A,x,x).
3919 
3920   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3921   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3922   `MatForwardSolve()` solves $U^T*D y = b$, and
3923   `MatBackwardSolve()` solves $U x = y$.
3924   Thus they do not provide a symmetric preconditioner.
3925 
3926 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3927 @*/
3928 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3929 {
3930   PetscFunctionBegin;
3931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3932   PetscValidType(mat, 1);
3933   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3934   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3935   PetscCheckSameComm(mat, 1, b, 2);
3936   PetscCheckSameComm(mat, 1, x, 3);
3937   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3938   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);
3939   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);
3940   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);
3941   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3942   MatCheckPreallocated(mat, 1);
3943 
3944   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3945   PetscUseTypeMethod(mat, backwardsolve, b, x);
3946   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3947   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3948   PetscFunctionReturn(PETSC_SUCCESS);
3949 }
3950 
3951 /*@
3952   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3953 
3954   Neighbor-wise Collective
3955 
3956   Input Parameters:
3957 + mat - the factored matrix
3958 . b   - the right-hand-side vector
3959 - y   - the vector to be added to
3960 
3961   Output Parameter:
3962 . x - the result vector
3963 
3964   Level: developer
3965 
3966   Note:
3967   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3968   call `MatSolveAdd`(A,x,y,x).
3969 
3970 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3971 @*/
3972 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3973 {
3974   PetscScalar one = 1.0;
3975   Vec         tmp;
3976 
3977   PetscFunctionBegin;
3978   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3979   PetscValidType(mat, 1);
3980   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3981   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3982   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3983   PetscCheckSameComm(mat, 1, b, 2);
3984   PetscCheckSameComm(mat, 1, y, 3);
3985   PetscCheckSameComm(mat, 1, x, 4);
3986   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3987   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);
3988   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);
3989   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);
3990   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);
3991   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);
3992   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3993   MatCheckPreallocated(mat, 1);
3994 
3995   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3996   if (mat->factorerrortype) {
3997     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3998     PetscCall(VecSetInf(x));
3999   } else if (mat->ops->solveadd) {
4000     PetscUseTypeMethod(mat, solveadd, b, y, x);
4001   } else {
4002     /* do the solve then the add manually */
4003     if (x != y) {
4004       PetscCall(MatSolve(mat, b, x));
4005       PetscCall(VecAXPY(x, one, y));
4006     } else {
4007       PetscCall(VecDuplicate(x, &tmp));
4008       PetscCall(VecCopy(x, tmp));
4009       PetscCall(MatSolve(mat, b, x));
4010       PetscCall(VecAXPY(x, one, tmp));
4011       PetscCall(VecDestroy(&tmp));
4012     }
4013   }
4014   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4015   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4016   PetscFunctionReturn(PETSC_SUCCESS);
4017 }
4018 
4019 /*@
4020   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4021 
4022   Neighbor-wise Collective
4023 
4024   Input Parameters:
4025 + mat - the factored matrix
4026 - b   - the right-hand-side vector
4027 
4028   Output Parameter:
4029 . x - the result vector
4030 
4031   Level: developer
4032 
4033   Notes:
4034   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4035   call `MatSolveTranspose`(A,x,x).
4036 
4037   Most users should employ the `KSP` interface for linear solvers
4038   instead of working directly with matrix algebra routines such as this.
4039   See, e.g., `KSPCreate()`.
4040 
4041 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4042 @*/
4043 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4044 {
4045   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4046 
4047   PetscFunctionBegin;
4048   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4049   PetscValidType(mat, 1);
4050   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4051   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4052   PetscCheckSameComm(mat, 1, b, 2);
4053   PetscCheckSameComm(mat, 1, x, 3);
4054   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4055   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);
4056   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);
4057   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4058   MatCheckPreallocated(mat, 1);
4059   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4060   if (mat->factorerrortype) {
4061     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4062     PetscCall(VecSetInf(x));
4063   } else {
4064     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4065     PetscCall((*f)(mat, b, x));
4066   }
4067   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4068   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4069   PetscFunctionReturn(PETSC_SUCCESS);
4070 }
4071 
4072 /*@
4073   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4074   factored matrix.
4075 
4076   Neighbor-wise Collective
4077 
4078   Input Parameters:
4079 + mat - the factored matrix
4080 . b   - the right-hand-side vector
4081 - y   - the vector to be added to
4082 
4083   Output Parameter:
4084 . x - the result vector
4085 
4086   Level: developer
4087 
4088   Note:
4089   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4090   call `MatSolveTransposeAdd`(A,x,y,x).
4091 
4092 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4093 @*/
4094 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4095 {
4096   PetscScalar one = 1.0;
4097   Vec         tmp;
4098   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4099 
4100   PetscFunctionBegin;
4101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4102   PetscValidType(mat, 1);
4103   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4104   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4105   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4106   PetscCheckSameComm(mat, 1, b, 2);
4107   PetscCheckSameComm(mat, 1, y, 3);
4108   PetscCheckSameComm(mat, 1, x, 4);
4109   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4110   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);
4111   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);
4112   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);
4113   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);
4114   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4115   MatCheckPreallocated(mat, 1);
4116 
4117   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4118   if (mat->factorerrortype) {
4119     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4120     PetscCall(VecSetInf(x));
4121   } else if (f) {
4122     PetscCall((*f)(mat, b, y, x));
4123   } else {
4124     /* do the solve then the add manually */
4125     if (x != y) {
4126       PetscCall(MatSolveTranspose(mat, b, x));
4127       PetscCall(VecAXPY(x, one, y));
4128     } else {
4129       PetscCall(VecDuplicate(x, &tmp));
4130       PetscCall(VecCopy(x, tmp));
4131       PetscCall(MatSolveTranspose(mat, b, x));
4132       PetscCall(VecAXPY(x, one, tmp));
4133       PetscCall(VecDestroy(&tmp));
4134     }
4135   }
4136   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4137   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4138   PetscFunctionReturn(PETSC_SUCCESS);
4139 }
4140 
4141 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4142 /*@
4143   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4144 
4145   Neighbor-wise Collective
4146 
4147   Input Parameters:
4148 + mat   - the matrix
4149 . b     - the right-hand side
4150 . omega - the relaxation factor
4151 . flag  - flag indicating the type of SOR (see below)
4152 . shift - diagonal shift
4153 . its   - the number of iterations
4154 - lits  - the number of local iterations
4155 
4156   Output Parameter:
4157 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4158 
4159   SOR Flags:
4160 +     `SOR_FORWARD_SWEEP` - forward SOR
4161 .     `SOR_BACKWARD_SWEEP` - backward SOR
4162 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4163 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4164 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4165 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4166 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4167 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4168   upper/lower triangular part of matrix to
4169   vector (with omega)
4170 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4171 
4172   Level: developer
4173 
4174   Notes:
4175   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4176   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4177   on each processor.
4178 
4179   Application programmers will not generally use `MatSOR()` directly,
4180   but instead will employ the `KSP`/`PC` interface.
4181 
4182   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4183 
4184   Most users should employ the `KSP` interface for linear solvers
4185   instead of working directly with matrix algebra routines such as this.
4186   See, e.g., `KSPCreate()`.
4187 
4188   Vectors `x` and `b` CANNOT be the same
4189 
4190   The flags are implemented as bitwise inclusive or operations.
4191   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4192   to specify a zero initial guess for SSOR.
4193 
4194   Developer Note:
4195   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4196 
4197 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4198 @*/
4199 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4200 {
4201   PetscFunctionBegin;
4202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4203   PetscValidType(mat, 1);
4204   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4205   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4206   PetscCheckSameComm(mat, 1, b, 2);
4207   PetscCheckSameComm(mat, 1, x, 8);
4208   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4209   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4210   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);
4211   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);
4212   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);
4213   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4214   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4215   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4216 
4217   MatCheckPreallocated(mat, 1);
4218   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4219   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4220   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4221   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4222   PetscFunctionReturn(PETSC_SUCCESS);
4223 }
4224 
4225 /*
4226       Default matrix copy routine.
4227 */
4228 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4229 {
4230   PetscInt           i, rstart = 0, rend = 0, nz;
4231   const PetscInt    *cwork;
4232   const PetscScalar *vwork;
4233 
4234   PetscFunctionBegin;
4235   if (B->assembled) PetscCall(MatZeroEntries(B));
4236   if (str == SAME_NONZERO_PATTERN) {
4237     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4238     for (i = rstart; i < rend; i++) {
4239       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4240       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4241       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4242     }
4243   } else {
4244     PetscCall(MatAYPX(B, 0.0, A, str));
4245   }
4246   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4247   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4248   PetscFunctionReturn(PETSC_SUCCESS);
4249 }
4250 
4251 /*@
4252   MatCopy - Copies a matrix to another matrix.
4253 
4254   Collective
4255 
4256   Input Parameters:
4257 + A   - the matrix
4258 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4259 
4260   Output Parameter:
4261 . B - where the copy is put
4262 
4263   Level: intermediate
4264 
4265   Notes:
4266   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4267 
4268   `MatCopy()` copies the matrix entries of a matrix to another existing
4269   matrix (after first zeroing the second matrix).  A related routine is
4270   `MatConvert()`, which first creates a new matrix and then copies the data.
4271 
4272 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4273 @*/
4274 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4275 {
4276   PetscInt i;
4277 
4278   PetscFunctionBegin;
4279   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4280   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4281   PetscValidType(A, 1);
4282   PetscValidType(B, 2);
4283   PetscCheckSameComm(A, 1, B, 2);
4284   MatCheckPreallocated(B, 2);
4285   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4286   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4287   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,
4288              A->cmap->N, B->cmap->N);
4289   MatCheckPreallocated(A, 1);
4290   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4291 
4292   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4293   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4294   else PetscCall(MatCopy_Basic(A, B, str));
4295 
4296   B->stencil.dim = A->stencil.dim;
4297   B->stencil.noc = A->stencil.noc;
4298   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4299     B->stencil.dims[i]   = A->stencil.dims[i];
4300     B->stencil.starts[i] = A->stencil.starts[i];
4301   }
4302 
4303   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4304   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4305   PetscFunctionReturn(PETSC_SUCCESS);
4306 }
4307 
4308 /*@
4309   MatConvert - Converts a matrix to another matrix, either of the same
4310   or different type.
4311 
4312   Collective
4313 
4314   Input Parameters:
4315 + mat     - the matrix
4316 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4317             same type as the original matrix.
4318 - reuse   - denotes if the destination matrix is to be created or reused.
4319             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
4320             `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).
4321 
4322   Output Parameter:
4323 . M - pointer to place new matrix
4324 
4325   Level: intermediate
4326 
4327   Notes:
4328   `MatConvert()` first creates a new matrix and then copies the data from
4329   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4330   entries of one matrix to another already existing matrix context.
4331 
4332   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4333   the MPI communicator of the generated matrix is always the same as the communicator
4334   of the input matrix.
4335 
4336 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4337 @*/
4338 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4339 {
4340   PetscBool  sametype, issame, flg;
4341   PetscBool3 issymmetric, ishermitian;
4342   char       convname[256], mtype[256];
4343   Mat        B;
4344 
4345   PetscFunctionBegin;
4346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4347   PetscValidType(mat, 1);
4348   PetscAssertPointer(M, 4);
4349   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4350   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4351   MatCheckPreallocated(mat, 1);
4352 
4353   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4354   if (flg) newtype = mtype;
4355 
4356   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4357   PetscCall(PetscStrcmp(newtype, "same", &issame));
4358   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4359   if (reuse == MAT_REUSE_MATRIX) {
4360     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4361     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4362   }
4363 
4364   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4365     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4366     PetscFunctionReturn(PETSC_SUCCESS);
4367   }
4368 
4369   /* Cache Mat options because some converters use MatHeaderReplace  */
4370   issymmetric = mat->symmetric;
4371   ishermitian = mat->hermitian;
4372 
4373   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4374     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4375     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4376   } else {
4377     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4378     const char *prefix[3]                                 = {"seq", "mpi", ""};
4379     PetscInt    i;
4380     /*
4381        Order of precedence:
4382        0) See if newtype is a superclass of the current matrix.
4383        1) See if a specialized converter is known to the current matrix.
4384        2) See if a specialized converter is known to the desired matrix class.
4385        3) See if a good general converter is registered for the desired class
4386           (as of 6/27/03 only MATMPIADJ falls into this category).
4387        4) See if a good general converter is known for the current matrix.
4388        5) Use a really basic converter.
4389     */
4390 
4391     /* 0) See if newtype is a superclass of the current matrix.
4392           i.e mat is mpiaij and newtype is aij */
4393     for (i = 0; i < 2; i++) {
4394       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4396       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4397       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4398       if (flg) {
4399         if (reuse == MAT_INPLACE_MATRIX) {
4400           PetscCall(PetscInfo(mat, "Early return\n"));
4401           PetscFunctionReturn(PETSC_SUCCESS);
4402         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4403           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4404           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4405           PetscFunctionReturn(PETSC_SUCCESS);
4406         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4407           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4408           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4409           PetscFunctionReturn(PETSC_SUCCESS);
4410         }
4411       }
4412     }
4413     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4414     for (i = 0; i < 3; i++) {
4415       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4416       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4417       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4418       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4419       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4420       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4421       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4422       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4423       if (conv) goto foundconv;
4424     }
4425 
4426     /* 2)  See if a specialized converter is known to the desired matrix class. */
4427     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4428     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4429     PetscCall(MatSetType(B, newtype));
4430     for (i = 0; i < 3; i++) {
4431       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4432       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4433       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4434       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4435       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4436       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4437       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4438       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4439       if (conv) {
4440         PetscCall(MatDestroy(&B));
4441         goto foundconv;
4442       }
4443     }
4444 
4445     /* 3) See if a good general converter is registered for the desired class */
4446     conv = B->ops->convertfrom;
4447     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4448     PetscCall(MatDestroy(&B));
4449     if (conv) goto foundconv;
4450 
4451     /* 4) See if a good general converter is known for the current matrix */
4452     if (mat->ops->convert) conv = mat->ops->convert;
4453     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4454     if (conv) goto foundconv;
4455 
4456     /* 5) Use a really basic converter. */
4457     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4458     conv = MatConvert_Basic;
4459 
4460   foundconv:
4461     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4462     PetscCall((*conv)(mat, newtype, reuse, M));
4463     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4464       /* the block sizes must be same if the mappings are copied over */
4465       (*M)->rmap->bs = mat->rmap->bs;
4466       (*M)->cmap->bs = mat->cmap->bs;
4467       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4468       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4469       (*M)->rmap->mapping = mat->rmap->mapping;
4470       (*M)->cmap->mapping = mat->cmap->mapping;
4471     }
4472     (*M)->stencil.dim = mat->stencil.dim;
4473     (*M)->stencil.noc = mat->stencil.noc;
4474     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4475       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4476       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4477     }
4478     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4479   }
4480   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4481 
4482   /* Copy Mat options */
4483   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4484   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4485   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4486   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4487   PetscFunctionReturn(PETSC_SUCCESS);
4488 }
4489 
4490 /*@C
4491   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4492 
4493   Not Collective
4494 
4495   Input Parameter:
4496 . mat - the matrix, must be a factored matrix
4497 
4498   Output Parameter:
4499 . type - the string name of the package (do not free this string)
4500 
4501   Level: intermediate
4502 
4503   Fortran Note:
4504   Pass in an empty string that is long enough and the package name will be copied into it.
4505 
4506 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4507 @*/
4508 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4509 {
4510   PetscErrorCode (*conv)(Mat, MatSolverType *);
4511 
4512   PetscFunctionBegin;
4513   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4514   PetscValidType(mat, 1);
4515   PetscAssertPointer(type, 2);
4516   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4517   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4518   if (conv) PetscCall((*conv)(mat, type));
4519   else *type = MATSOLVERPETSC;
4520   PetscFunctionReturn(PETSC_SUCCESS);
4521 }
4522 
4523 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4524 struct _MatSolverTypeForSpecifcType {
4525   MatType mtype;
4526   /* no entry for MAT_FACTOR_NONE */
4527   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4528   MatSolverTypeForSpecifcType next;
4529 };
4530 
4531 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4532 struct _MatSolverTypeHolder {
4533   char                       *name;
4534   MatSolverTypeForSpecifcType handlers;
4535   MatSolverTypeHolder         next;
4536 };
4537 
4538 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4539 
4540 /*@C
4541   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4542 
4543   Logically Collective, No Fortran Support
4544 
4545   Input Parameters:
4546 + package      - name of the package, for example petsc or superlu
4547 . mtype        - the matrix type that works with this package
4548 . ftype        - the type of factorization supported by the package
4549 - createfactor - routine that will create the factored matrix ready to be used
4550 
4551   Level: developer
4552 
4553 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4554   `MatGetFactor()`
4555 @*/
4556 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4557 {
4558   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4559   PetscBool                   flg;
4560   MatSolverTypeForSpecifcType inext, iprev = NULL;
4561 
4562   PetscFunctionBegin;
4563   PetscCall(MatInitializePackage());
4564   if (!next) {
4565     PetscCall(PetscNew(&MatSolverTypeHolders));
4566     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4567     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4568     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4569     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4570     PetscFunctionReturn(PETSC_SUCCESS);
4571   }
4572   while (next) {
4573     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4574     if (flg) {
4575       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4576       inext = next->handlers;
4577       while (inext) {
4578         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4579         if (flg) {
4580           inext->createfactor[(int)ftype - 1] = createfactor;
4581           PetscFunctionReturn(PETSC_SUCCESS);
4582         }
4583         iprev = inext;
4584         inext = inext->next;
4585       }
4586       PetscCall(PetscNew(&iprev->next));
4587       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4588       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4589       PetscFunctionReturn(PETSC_SUCCESS);
4590     }
4591     prev = next;
4592     next = next->next;
4593   }
4594   PetscCall(PetscNew(&prev->next));
4595   PetscCall(PetscStrallocpy(package, &prev->next->name));
4596   PetscCall(PetscNew(&prev->next->handlers));
4597   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4598   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4599   PetscFunctionReturn(PETSC_SUCCESS);
4600 }
4601 
4602 /*@C
4603   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4604 
4605   Input Parameters:
4606 + 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
4607 . ftype - the type of factorization supported by the type
4608 - mtype - the matrix type that works with this type
4609 
4610   Output Parameters:
4611 + foundtype    - `PETSC_TRUE` if the type was registered
4612 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4613 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4614 
4615   Calling sequence of `createfactor`:
4616 + A     - the matrix providing the factor matrix
4617 . mtype - the `MatType` of the factor requested
4618 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4619 
4620   Level: developer
4621 
4622   Note:
4623   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4624   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4625   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4626 
4627 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4628           `MatInitializePackage()`
4629 @*/
4630 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4631 {
4632   MatSolverTypeHolder         next = MatSolverTypeHolders;
4633   PetscBool                   flg;
4634   MatSolverTypeForSpecifcType inext;
4635 
4636   PetscFunctionBegin;
4637   if (foundtype) *foundtype = PETSC_FALSE;
4638   if (foundmtype) *foundmtype = PETSC_FALSE;
4639   if (createfactor) *createfactor = NULL;
4640 
4641   if (type) {
4642     while (next) {
4643       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4644       if (flg) {
4645         if (foundtype) *foundtype = PETSC_TRUE;
4646         inext = next->handlers;
4647         while (inext) {
4648           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4649           if (flg) {
4650             if (foundmtype) *foundmtype = PETSC_TRUE;
4651             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4652             PetscFunctionReturn(PETSC_SUCCESS);
4653           }
4654           inext = inext->next;
4655         }
4656       }
4657       next = next->next;
4658     }
4659   } else {
4660     while (next) {
4661       inext = next->handlers;
4662       while (inext) {
4663         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4664         if (flg && inext->createfactor[(int)ftype - 1]) {
4665           if (foundtype) *foundtype = PETSC_TRUE;
4666           if (foundmtype) *foundmtype = PETSC_TRUE;
4667           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4668           PetscFunctionReturn(PETSC_SUCCESS);
4669         }
4670         inext = inext->next;
4671       }
4672       next = next->next;
4673     }
4674     /* try with base classes inext->mtype */
4675     next = MatSolverTypeHolders;
4676     while (next) {
4677       inext = next->handlers;
4678       while (inext) {
4679         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4680         if (flg && inext->createfactor[(int)ftype - 1]) {
4681           if (foundtype) *foundtype = PETSC_TRUE;
4682           if (foundmtype) *foundmtype = PETSC_TRUE;
4683           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4684           PetscFunctionReturn(PETSC_SUCCESS);
4685         }
4686         inext = inext->next;
4687       }
4688       next = next->next;
4689     }
4690   }
4691   PetscFunctionReturn(PETSC_SUCCESS);
4692 }
4693 
4694 PetscErrorCode MatSolverTypeDestroy(void)
4695 {
4696   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4697   MatSolverTypeForSpecifcType inext, iprev;
4698 
4699   PetscFunctionBegin;
4700   while (next) {
4701     PetscCall(PetscFree(next->name));
4702     inext = next->handlers;
4703     while (inext) {
4704       PetscCall(PetscFree(inext->mtype));
4705       iprev = inext;
4706       inext = inext->next;
4707       PetscCall(PetscFree(iprev));
4708     }
4709     prev = next;
4710     next = next->next;
4711     PetscCall(PetscFree(prev));
4712   }
4713   MatSolverTypeHolders = NULL;
4714   PetscFunctionReturn(PETSC_SUCCESS);
4715 }
4716 
4717 /*@
4718   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4719 
4720   Logically Collective
4721 
4722   Input Parameter:
4723 . mat - the matrix
4724 
4725   Output Parameter:
4726 . flg - `PETSC_TRUE` if uses the ordering
4727 
4728   Level: developer
4729 
4730   Note:
4731   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4732   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4733 
4734 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4735 @*/
4736 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4737 {
4738   PetscFunctionBegin;
4739   *flg = mat->canuseordering;
4740   PetscFunctionReturn(PETSC_SUCCESS);
4741 }
4742 
4743 /*@
4744   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4745 
4746   Logically Collective
4747 
4748   Input Parameters:
4749 + mat   - the matrix obtained with `MatGetFactor()`
4750 - ftype - the factorization type to be used
4751 
4752   Output Parameter:
4753 . otype - the preferred ordering type
4754 
4755   Level: developer
4756 
4757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4758 @*/
4759 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4760 {
4761   PetscFunctionBegin;
4762   *otype = mat->preferredordering[ftype];
4763   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4764   PetscFunctionReturn(PETSC_SUCCESS);
4765 }
4766 
4767 /*@
4768   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4769 
4770   Collective
4771 
4772   Input Parameters:
4773 + mat   - the matrix
4774 . 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
4775           the other criteria is returned
4776 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4777 
4778   Output Parameter:
4779 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4780 
4781   Options Database Keys:
4782 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4783 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4784                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4785 
4786   Level: intermediate
4787 
4788   Notes:
4789   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4790   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4791 
4792   Users usually access the factorization solvers via `KSP`
4793 
4794   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4795   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
4796 
4797   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4798   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4799   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4800 
4801   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4802   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4803   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4804 
4805   Developer Note:
4806   This should actually be called `MatCreateFactor()` since it creates a new factor object
4807 
4808 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4809           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4810           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4811 @*/
4812 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4813 {
4814   PetscBool foundtype, foundmtype;
4815   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4816 
4817   PetscFunctionBegin;
4818   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4819   PetscValidType(mat, 1);
4820 
4821   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4822   MatCheckPreallocated(mat, 1);
4823 
4824   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4825   if (!foundtype) {
4826     if (type) {
4827       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],
4828               ((PetscObject)mat)->type_name, type);
4829     } else {
4830       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);
4831     }
4832   }
4833   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4834   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);
4835 
4836   PetscCall((*conv)(mat, ftype, f));
4837   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4838   PetscFunctionReturn(PETSC_SUCCESS);
4839 }
4840 
4841 /*@
4842   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4843 
4844   Not Collective
4845 
4846   Input Parameters:
4847 + mat   - the matrix
4848 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4849 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4850 
4851   Output Parameter:
4852 . flg - PETSC_TRUE if the factorization is available
4853 
4854   Level: intermediate
4855 
4856   Notes:
4857   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4858   such as pastix, superlu, mumps etc.
4859 
4860   PETSc must have been ./configure to use the external solver, using the option --download-package
4861 
4862   Developer Note:
4863   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4864 
4865 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4866           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4867 @*/
4868 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4869 {
4870   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4871 
4872   PetscFunctionBegin;
4873   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4874   PetscAssertPointer(flg, 4);
4875 
4876   *flg = PETSC_FALSE;
4877   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4878 
4879   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4880   MatCheckPreallocated(mat, 1);
4881 
4882   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4883   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4884   PetscFunctionReturn(PETSC_SUCCESS);
4885 }
4886 
4887 /*@
4888   MatDuplicate - Duplicates a matrix including the non-zero structure.
4889 
4890   Collective
4891 
4892   Input Parameters:
4893 + mat - the matrix
4894 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4895         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4896 
4897   Output Parameter:
4898 . M - pointer to place new matrix
4899 
4900   Level: intermediate
4901 
4902   Notes:
4903   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4904 
4905   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4906 
4907   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.
4908 
4909   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4910   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4911   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4912 
4913 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4914 @*/
4915 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4916 {
4917   Mat         B;
4918   VecType     vtype;
4919   PetscInt    i;
4920   PetscObject dm, container_h, container_d;
4921   void (*viewf)(void);
4922 
4923   PetscFunctionBegin;
4924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4925   PetscValidType(mat, 1);
4926   PetscAssertPointer(M, 3);
4927   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4928   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4929   MatCheckPreallocated(mat, 1);
4930 
4931   *M = NULL;
4932   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4933   PetscUseTypeMethod(mat, duplicate, op, M);
4934   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4935   B = *M;
4936 
4937   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4938   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4939   PetscCall(MatGetVecType(mat, &vtype));
4940   PetscCall(MatSetVecType(B, vtype));
4941 
4942   B->stencil.dim = mat->stencil.dim;
4943   B->stencil.noc = mat->stencil.noc;
4944   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4945     B->stencil.dims[i]   = mat->stencil.dims[i];
4946     B->stencil.starts[i] = mat->stencil.starts[i];
4947   }
4948 
4949   B->nooffproczerorows = mat->nooffproczerorows;
4950   B->nooffprocentries  = mat->nooffprocentries;
4951 
4952   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4953   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4954   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4955   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4956   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4957   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4958   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4959   PetscFunctionReturn(PETSC_SUCCESS);
4960 }
4961 
4962 /*@
4963   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4964 
4965   Logically Collective
4966 
4967   Input Parameter:
4968 . mat - the matrix
4969 
4970   Output Parameter:
4971 . v - the diagonal of the matrix
4972 
4973   Level: intermediate
4974 
4975   Note:
4976   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4977   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4978   is larger than `ndiag`, the values of the remaining entries are unspecified.
4979 
4980   Currently only correct in parallel for square matrices.
4981 
4982 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4983 @*/
4984 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4985 {
4986   PetscFunctionBegin;
4987   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4988   PetscValidType(mat, 1);
4989   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4990   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4991   MatCheckPreallocated(mat, 1);
4992   if (PetscDefined(USE_DEBUG)) {
4993     PetscInt nv, row, col, ndiag;
4994 
4995     PetscCall(VecGetLocalSize(v, &nv));
4996     PetscCall(MatGetLocalSize(mat, &row, &col));
4997     ndiag = PetscMin(row, col);
4998     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);
4999   }
5000 
5001   PetscUseTypeMethod(mat, getdiagonal, v);
5002   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5003   PetscFunctionReturn(PETSC_SUCCESS);
5004 }
5005 
5006 /*@
5007   MatGetRowMin - Gets the minimum value (of the real part) of each
5008   row of the matrix
5009 
5010   Logically Collective
5011 
5012   Input Parameter:
5013 . mat - the matrix
5014 
5015   Output Parameters:
5016 + v   - the vector for storing the maximums
5017 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5018 
5019   Level: intermediate
5020 
5021   Note:
5022   The result of this call are the same as if one converted the matrix to dense format
5023   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5024 
5025   This code is only implemented for a couple of matrix formats.
5026 
5027 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5028           `MatGetRowMax()`
5029 @*/
5030 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5031 {
5032   PetscFunctionBegin;
5033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5034   PetscValidType(mat, 1);
5035   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5036   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5037 
5038   if (!mat->cmap->N) {
5039     PetscCall(VecSet(v, PETSC_MAX_REAL));
5040     if (idx) {
5041       PetscInt i, m = mat->rmap->n;
5042       for (i = 0; i < m; i++) idx[i] = -1;
5043     }
5044   } else {
5045     MatCheckPreallocated(mat, 1);
5046   }
5047   PetscUseTypeMethod(mat, getrowmin, v, idx);
5048   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5049   PetscFunctionReturn(PETSC_SUCCESS);
5050 }
5051 
5052 /*@
5053   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5054   row of the matrix
5055 
5056   Logically Collective
5057 
5058   Input Parameter:
5059 . mat - the matrix
5060 
5061   Output Parameters:
5062 + v   - the vector for storing the minimums
5063 - idx - the indices of the column found for each row (or `NULL` if not needed)
5064 
5065   Level: intermediate
5066 
5067   Notes:
5068   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5069   row is 0 (the first column).
5070 
5071   This code is only implemented for a couple of matrix formats.
5072 
5073 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5074 @*/
5075 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5076 {
5077   PetscFunctionBegin;
5078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5079   PetscValidType(mat, 1);
5080   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5081   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5082   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5083 
5084   if (!mat->cmap->N) {
5085     PetscCall(VecSet(v, 0.0));
5086     if (idx) {
5087       PetscInt i, m = mat->rmap->n;
5088       for (i = 0; i < m; i++) idx[i] = -1;
5089     }
5090   } else {
5091     MatCheckPreallocated(mat, 1);
5092     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5093     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5094   }
5095   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5096   PetscFunctionReturn(PETSC_SUCCESS);
5097 }
5098 
5099 /*@
5100   MatGetRowMax - Gets the maximum value (of the real part) of each
5101   row of the matrix
5102 
5103   Logically Collective
5104 
5105   Input Parameter:
5106 . mat - the matrix
5107 
5108   Output Parameters:
5109 + v   - the vector for storing the maximums
5110 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5111 
5112   Level: intermediate
5113 
5114   Notes:
5115   The result of this call are the same as if one converted the matrix to dense format
5116   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5117 
5118   This code is only implemented for a couple of matrix formats.
5119 
5120 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5121 @*/
5122 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5123 {
5124   PetscFunctionBegin;
5125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5126   PetscValidType(mat, 1);
5127   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5128   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5129 
5130   if (!mat->cmap->N) {
5131     PetscCall(VecSet(v, PETSC_MIN_REAL));
5132     if (idx) {
5133       PetscInt i, m = mat->rmap->n;
5134       for (i = 0; i < m; i++) idx[i] = -1;
5135     }
5136   } else {
5137     MatCheckPreallocated(mat, 1);
5138     PetscUseTypeMethod(mat, getrowmax, v, idx);
5139   }
5140   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5141   PetscFunctionReturn(PETSC_SUCCESS);
5142 }
5143 
5144 /*@
5145   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5146   row of the matrix
5147 
5148   Logically Collective
5149 
5150   Input Parameter:
5151 . mat - the matrix
5152 
5153   Output Parameters:
5154 + v   - the vector for storing the maximums
5155 - idx - the indices of the column found for each row (or `NULL` if not needed)
5156 
5157   Level: intermediate
5158 
5159   Notes:
5160   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5161   row is 0 (the first column).
5162 
5163   This code is only implemented for a couple of matrix formats.
5164 
5165 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5166 @*/
5167 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
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 
5175   if (!mat->cmap->N) {
5176     PetscCall(VecSet(v, 0.0));
5177     if (idx) {
5178       PetscInt i, m = mat->rmap->n;
5179       for (i = 0; i < m; i++) idx[i] = -1;
5180     }
5181   } else {
5182     MatCheckPreallocated(mat, 1);
5183     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5184     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5185   }
5186   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5187   PetscFunctionReturn(PETSC_SUCCESS);
5188 }
5189 
5190 /*@
5191   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5192 
5193   Logically Collective
5194 
5195   Input Parameter:
5196 . mat - the matrix
5197 
5198   Output Parameter:
5199 . v - the vector for storing the sum
5200 
5201   Level: intermediate
5202 
5203   This code is only implemented for a couple of matrix formats.
5204 
5205 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5206 @*/
5207 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5208 {
5209   PetscFunctionBegin;
5210   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5211   PetscValidType(mat, 1);
5212   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5213   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5214 
5215   if (!mat->cmap->N) {
5216     PetscCall(VecSet(v, 0.0));
5217   } else {
5218     MatCheckPreallocated(mat, 1);
5219     PetscUseTypeMethod(mat, getrowsumabs, v);
5220   }
5221   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5222   PetscFunctionReturn(PETSC_SUCCESS);
5223 }
5224 
5225 /*@
5226   MatGetRowSum - Gets the sum of each row of the matrix
5227 
5228   Logically or Neighborhood Collective
5229 
5230   Input Parameter:
5231 . mat - the matrix
5232 
5233   Output Parameter:
5234 . v - the vector for storing the sum of rows
5235 
5236   Level: intermediate
5237 
5238   Note:
5239   This code is slow since it is not currently specialized for different formats
5240 
5241 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5242 @*/
5243 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5244 {
5245   Vec ones;
5246 
5247   PetscFunctionBegin;
5248   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5249   PetscValidType(mat, 1);
5250   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5251   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5252   MatCheckPreallocated(mat, 1);
5253   PetscCall(MatCreateVecs(mat, &ones, NULL));
5254   PetscCall(VecSet(ones, 1.));
5255   PetscCall(MatMult(mat, ones, v));
5256   PetscCall(VecDestroy(&ones));
5257   PetscFunctionReturn(PETSC_SUCCESS);
5258 }
5259 
5260 /*@
5261   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5262   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5263 
5264   Collective
5265 
5266   Input Parameter:
5267 . mat - the matrix to provide the transpose
5268 
5269   Output Parameter:
5270 . 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
5271 
5272   Level: advanced
5273 
5274   Note:
5275   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
5276   routine allows bypassing that call.
5277 
5278 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5279 @*/
5280 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5281 {
5282   PetscContainer  rB = NULL;
5283   MatParentState *rb = NULL;
5284 
5285   PetscFunctionBegin;
5286   PetscCall(PetscNew(&rb));
5287   rb->id    = ((PetscObject)mat)->id;
5288   rb->state = 0;
5289   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5290   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5291   PetscCall(PetscContainerSetPointer(rB, rb));
5292   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5293   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5294   PetscCall(PetscObjectDereference((PetscObject)rB));
5295   PetscFunctionReturn(PETSC_SUCCESS);
5296 }
5297 
5298 /*@
5299   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5300 
5301   Collective
5302 
5303   Input Parameters:
5304 + mat   - the matrix to transpose
5305 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5306 
5307   Output Parameter:
5308 . B - the transpose
5309 
5310   Level: intermediate
5311 
5312   Notes:
5313   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5314 
5315   `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
5316   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5317 
5318   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.
5319 
5320   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5321 
5322   If mat is unchanged from the last call this function returns immediately without recomputing the result
5323 
5324   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5325 
5326 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5327           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5328 @*/
5329 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5330 {
5331   PetscContainer  rB = NULL;
5332   MatParentState *rb = NULL;
5333 
5334   PetscFunctionBegin;
5335   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5336   PetscValidType(mat, 1);
5337   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5338   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5339   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5340   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5341   MatCheckPreallocated(mat, 1);
5342   if (reuse == MAT_REUSE_MATRIX) {
5343     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5344     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5345     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5346     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5347     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5348   }
5349 
5350   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5351   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5352     PetscUseTypeMethod(mat, transpose, reuse, B);
5353     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5354   }
5355   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5356 
5357   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5358   if (reuse != MAT_INPLACE_MATRIX) {
5359     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5360     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5361     rb->state        = ((PetscObject)mat)->state;
5362     rb->nonzerostate = mat->nonzerostate;
5363   }
5364   PetscFunctionReturn(PETSC_SUCCESS);
5365 }
5366 
5367 /*@
5368   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5369 
5370   Collective
5371 
5372   Input Parameter:
5373 . A - the matrix to transpose
5374 
5375   Output Parameter:
5376 . 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
5377       numerical portion.
5378 
5379   Level: intermediate
5380 
5381   Note:
5382   This is not supported for many matrix types, use `MatTranspose()` in those cases
5383 
5384 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5385 @*/
5386 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5387 {
5388   PetscFunctionBegin;
5389   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5390   PetscValidType(A, 1);
5391   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5392   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5393   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5394   PetscUseTypeMethod(A, transposesymbolic, B);
5395   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5396 
5397   PetscCall(MatTransposeSetPrecursor(A, *B));
5398   PetscFunctionReturn(PETSC_SUCCESS);
5399 }
5400 
5401 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5402 {
5403   PetscContainer  rB;
5404   MatParentState *rb;
5405 
5406   PetscFunctionBegin;
5407   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5408   PetscValidType(A, 1);
5409   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5410   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5411   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5412   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5413   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5414   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5415   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5416   PetscFunctionReturn(PETSC_SUCCESS);
5417 }
5418 
5419 /*@
5420   MatIsTranspose - Test whether a matrix is another one's transpose,
5421   or its own, in which case it tests symmetry.
5422 
5423   Collective
5424 
5425   Input Parameters:
5426 + A   - the matrix to test
5427 . B   - the matrix to test against, this can equal the first parameter
5428 - tol - tolerance, differences between entries smaller than this are counted as zero
5429 
5430   Output Parameter:
5431 . flg - the result
5432 
5433   Level: intermediate
5434 
5435   Notes:
5436   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5437   test involves parallel copies of the block off-diagonal parts of the matrix.
5438 
5439 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5440 @*/
5441 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5442 {
5443   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5444 
5445   PetscFunctionBegin;
5446   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5447   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5448   PetscAssertPointer(flg, 4);
5449   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5450   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5451   *flg = PETSC_FALSE;
5452   if (f && g) {
5453     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5454     PetscCall((*f)(A, B, tol, flg));
5455   } else {
5456     MatType mattype;
5457 
5458     PetscCall(MatGetType(f ? B : A, &mattype));
5459     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5460   }
5461   PetscFunctionReturn(PETSC_SUCCESS);
5462 }
5463 
5464 /*@
5465   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5466 
5467   Collective
5468 
5469   Input Parameters:
5470 + mat   - the matrix to transpose and complex conjugate
5471 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5472 
5473   Output Parameter:
5474 . B - the Hermitian transpose
5475 
5476   Level: intermediate
5477 
5478 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5479 @*/
5480 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5481 {
5482   PetscFunctionBegin;
5483   PetscCall(MatTranspose(mat, reuse, B));
5484 #if defined(PETSC_USE_COMPLEX)
5485   PetscCall(MatConjugate(*B));
5486 #endif
5487   PetscFunctionReturn(PETSC_SUCCESS);
5488 }
5489 
5490 /*@
5491   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5492 
5493   Collective
5494 
5495   Input Parameters:
5496 + A   - the matrix to test
5497 . B   - the matrix to test against, this can equal the first parameter
5498 - tol - tolerance, differences between entries smaller than this are counted as zero
5499 
5500   Output Parameter:
5501 . flg - the result
5502 
5503   Level: intermediate
5504 
5505   Notes:
5506   Only available for `MATAIJ` matrices.
5507 
5508   The sequential algorithm
5509   has a running time of the order of the number of nonzeros; the parallel
5510   test involves parallel copies of the block off-diagonal parts of the matrix.
5511 
5512 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5513 @*/
5514 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5515 {
5516   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5517 
5518   PetscFunctionBegin;
5519   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5520   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5521   PetscAssertPointer(flg, 4);
5522   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5523   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5524   if (f && g) {
5525     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5526     PetscCall((*f)(A, B, tol, flg));
5527   }
5528   PetscFunctionReturn(PETSC_SUCCESS);
5529 }
5530 
5531 /*@
5532   MatPermute - Creates a new matrix with rows and columns permuted from the
5533   original.
5534 
5535   Collective
5536 
5537   Input Parameters:
5538 + mat - the matrix to permute
5539 . row - row permutation, each processor supplies only the permutation for its rows
5540 - col - column permutation, each processor supplies only the permutation for its columns
5541 
5542   Output Parameter:
5543 . B - the permuted matrix
5544 
5545   Level: advanced
5546 
5547   Note:
5548   The index sets map from row/col of permuted matrix to row/col of original matrix.
5549   The index sets should be on the same communicator as mat and have the same local sizes.
5550 
5551   Developer Note:
5552   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5553   exploit the fact that row and col are permutations, consider implementing the
5554   more general `MatCreateSubMatrix()` instead.
5555 
5556 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5557 @*/
5558 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5559 {
5560   PetscFunctionBegin;
5561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5562   PetscValidType(mat, 1);
5563   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5564   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5565   PetscAssertPointer(B, 4);
5566   PetscCheckSameComm(mat, 1, row, 2);
5567   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5568   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5569   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5570   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5571   MatCheckPreallocated(mat, 1);
5572 
5573   if (mat->ops->permute) {
5574     PetscUseTypeMethod(mat, permute, row, col, B);
5575     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5576   } else {
5577     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5578   }
5579   PetscFunctionReturn(PETSC_SUCCESS);
5580 }
5581 
5582 /*@
5583   MatEqual - Compares two matrices.
5584 
5585   Collective
5586 
5587   Input Parameters:
5588 + A - the first matrix
5589 - B - the second matrix
5590 
5591   Output Parameter:
5592 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5593 
5594   Level: intermediate
5595 
5596 .seealso: [](ch_matrices), `Mat`
5597 @*/
5598 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5599 {
5600   PetscFunctionBegin;
5601   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5602   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5603   PetscValidType(A, 1);
5604   PetscValidType(B, 2);
5605   PetscAssertPointer(flg, 3);
5606   PetscCheckSameComm(A, 1, B, 2);
5607   MatCheckPreallocated(A, 1);
5608   MatCheckPreallocated(B, 2);
5609   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5610   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5611   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,
5612              B->cmap->N);
5613   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5614     PetscUseTypeMethod(A, equal, B, flg);
5615   } else {
5616     PetscCall(MatMultEqual(A, B, 10, flg));
5617   }
5618   PetscFunctionReturn(PETSC_SUCCESS);
5619 }
5620 
5621 /*@
5622   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5623   matrices that are stored as vectors.  Either of the two scaling
5624   matrices can be `NULL`.
5625 
5626   Collective
5627 
5628   Input Parameters:
5629 + mat - the matrix to be scaled
5630 . l   - the left scaling vector (or `NULL`)
5631 - r   - the right scaling vector (or `NULL`)
5632 
5633   Level: intermediate
5634 
5635   Note:
5636   `MatDiagonalScale()` computes $A = LAR$, where
5637   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5638   The L scales the rows of the matrix, the R scales the columns of the matrix.
5639 
5640 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5641 @*/
5642 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5643 {
5644   PetscFunctionBegin;
5645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5646   PetscValidType(mat, 1);
5647   if (l) {
5648     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5649     PetscCheckSameComm(mat, 1, l, 2);
5650   }
5651   if (r) {
5652     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5653     PetscCheckSameComm(mat, 1, r, 3);
5654   }
5655   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5656   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5657   MatCheckPreallocated(mat, 1);
5658   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5659 
5660   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5661   PetscUseTypeMethod(mat, diagonalscale, l, r);
5662   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5663   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5664   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5665   PetscFunctionReturn(PETSC_SUCCESS);
5666 }
5667 
5668 /*@
5669   MatScale - Scales all elements of a matrix by a given number.
5670 
5671   Logically Collective
5672 
5673   Input Parameters:
5674 + mat - the matrix to be scaled
5675 - a   - the scaling value
5676 
5677   Level: intermediate
5678 
5679 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5680 @*/
5681 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5682 {
5683   PetscFunctionBegin;
5684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5685   PetscValidType(mat, 1);
5686   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5687   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5688   PetscValidLogicalCollectiveScalar(mat, a, 2);
5689   MatCheckPreallocated(mat, 1);
5690 
5691   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5692   if (a != (PetscScalar)1.0) {
5693     PetscUseTypeMethod(mat, scale, a);
5694     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5695   }
5696   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5697   PetscFunctionReturn(PETSC_SUCCESS);
5698 }
5699 
5700 /*@
5701   MatNorm - Calculates various norms of a matrix.
5702 
5703   Collective
5704 
5705   Input Parameters:
5706 + mat  - the matrix
5707 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5708 
5709   Output Parameter:
5710 . nrm - the resulting norm
5711 
5712   Level: intermediate
5713 
5714 .seealso: [](ch_matrices), `Mat`
5715 @*/
5716 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5717 {
5718   PetscFunctionBegin;
5719   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5720   PetscValidType(mat, 1);
5721   PetscAssertPointer(nrm, 3);
5722 
5723   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5724   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5725   MatCheckPreallocated(mat, 1);
5726 
5727   PetscUseTypeMethod(mat, norm, type, nrm);
5728   PetscFunctionReturn(PETSC_SUCCESS);
5729 }
5730 
5731 /*
5732      This variable is used to prevent counting of MatAssemblyBegin() that
5733    are called from within a MatAssemblyEnd().
5734 */
5735 static PetscInt MatAssemblyEnd_InUse = 0;
5736 /*@
5737   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5738   be called after completing all calls to `MatSetValues()`.
5739 
5740   Collective
5741 
5742   Input Parameters:
5743 + mat  - the matrix
5744 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5745 
5746   Level: beginner
5747 
5748   Notes:
5749   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5750   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5751 
5752   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5753   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5754   using the matrix.
5755 
5756   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5757   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
5758   a global collective operation requiring all processes that share the matrix.
5759 
5760   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5761   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5762   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5763 
5764 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5765 @*/
5766 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5767 {
5768   PetscFunctionBegin;
5769   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5770   PetscValidType(mat, 1);
5771   MatCheckPreallocated(mat, 1);
5772   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5773   if (mat->assembled) {
5774     mat->was_assembled = PETSC_TRUE;
5775     mat->assembled     = PETSC_FALSE;
5776   }
5777 
5778   if (!MatAssemblyEnd_InUse) {
5779     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5780     PetscTryTypeMethod(mat, assemblybegin, type);
5781     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5782   } else PetscTryTypeMethod(mat, assemblybegin, type);
5783   PetscFunctionReturn(PETSC_SUCCESS);
5784 }
5785 
5786 /*@
5787   MatAssembled - Indicates if a matrix has been assembled and is ready for
5788   use; for example, in matrix-vector product.
5789 
5790   Not Collective
5791 
5792   Input Parameter:
5793 . mat - the matrix
5794 
5795   Output Parameter:
5796 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5797 
5798   Level: advanced
5799 
5800 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5801 @*/
5802 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5803 {
5804   PetscFunctionBegin;
5805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5806   PetscAssertPointer(assembled, 2);
5807   *assembled = mat->assembled;
5808   PetscFunctionReturn(PETSC_SUCCESS);
5809 }
5810 
5811 /*@
5812   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5813   be called after `MatAssemblyBegin()`.
5814 
5815   Collective
5816 
5817   Input Parameters:
5818 + mat  - the matrix
5819 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5820 
5821   Options Database Keys:
5822 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5823 . -mat_view ::ascii_info_detail      - Prints more detailed info
5824 . -mat_view                          - Prints matrix in ASCII format
5825 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5826 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5827 . -display <name>                    - Sets display name (default is host)
5828 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5829 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5830 . -viewer_socket_machine <machine>   - Machine to use for socket
5831 . -viewer_socket_port <port>         - Port number to use for socket
5832 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5833 
5834   Level: beginner
5835 
5836 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5837 @*/
5838 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5839 {
5840   static PetscInt inassm = 0;
5841   PetscBool       flg    = PETSC_FALSE;
5842 
5843   PetscFunctionBegin;
5844   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5845   PetscValidType(mat, 1);
5846 
5847   inassm++;
5848   MatAssemblyEnd_InUse++;
5849   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5850     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5851     PetscTryTypeMethod(mat, assemblyend, type);
5852     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5853   } else PetscTryTypeMethod(mat, assemblyend, type);
5854 
5855   /* Flush assembly is not a true assembly */
5856   if (type != MAT_FLUSH_ASSEMBLY) {
5857     if (mat->num_ass) {
5858       if (!mat->symmetry_eternal) {
5859         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5860         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5861       }
5862       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5863       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5864     }
5865     mat->num_ass++;
5866     mat->assembled        = PETSC_TRUE;
5867     mat->ass_nonzerostate = mat->nonzerostate;
5868   }
5869 
5870   mat->insertmode = NOT_SET_VALUES;
5871   MatAssemblyEnd_InUse--;
5872   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5873   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5874     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5875 
5876     if (mat->checksymmetryonassembly) {
5877       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5878       if (flg) {
5879         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5880       } else {
5881         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5882       }
5883     }
5884     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5885   }
5886   inassm--;
5887   PetscFunctionReturn(PETSC_SUCCESS);
5888 }
5889 
5890 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5891 /*@
5892   MatSetOption - Sets a parameter option for a matrix. Some options
5893   may be specific to certain storage formats.  Some options
5894   determine how values will be inserted (or added). Sorted,
5895   row-oriented input will generally assemble the fastest. The default
5896   is row-oriented.
5897 
5898   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5899 
5900   Input Parameters:
5901 + mat - the matrix
5902 . op  - the option, one of those listed below (and possibly others),
5903 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5904 
5905   Options Describing Matrix Structure:
5906 + `MAT_SPD`                         - symmetric positive definite
5907 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5908 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5909 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5910 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5911 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5912 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5913 
5914    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5915    do not need to be computed (usually at a high cost)
5916 
5917    Options For Use with `MatSetValues()`:
5918    Insert a logically dense subblock, which can be
5919 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5920 
5921    These options reflect the data you pass in with `MatSetValues()`; it has
5922    nothing to do with how the data is stored internally in the matrix
5923    data structure.
5924 
5925    When (re)assembling a matrix, we can restrict the input for
5926    efficiency/debugging purposes.  These options include
5927 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5928 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5929 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5930 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5931 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5932 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5933         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5934         performance for very large process counts.
5935 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5936         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5937         functions, instead sending only neighbor messages.
5938 
5939   Level: intermediate
5940 
5941   Notes:
5942   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5943 
5944   Some options are relevant only for particular matrix types and
5945   are thus ignored by others.  Other options are not supported by
5946   certain matrix types and will generate an error message if set.
5947 
5948   If using Fortran to compute a matrix, one may need to
5949   use the column-oriented option (or convert to the row-oriented
5950   format).
5951 
5952   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5953   that would generate a new entry in the nonzero structure is instead
5954   ignored.  Thus, if memory has not already been allocated for this particular
5955   data, then the insertion is ignored. For dense matrices, in which
5956   the entire array is allocated, no entries are ever ignored.
5957   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5958 
5959   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5960   that would generate a new entry in the nonzero structure instead produces
5961   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
5962 
5963   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5964   that would generate a new entry that has not been preallocated will
5965   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5966   only.) This is a useful flag when debugging matrix memory preallocation.
5967   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5968 
5969   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5970   other processors should be dropped, rather than stashed.
5971   This is useful if you know that the "owning" processor is also
5972   always generating the correct matrix entries, so that PETSc need
5973   not transfer duplicate entries generated on another processor.
5974 
5975   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5976   searches during matrix assembly. When this flag is set, the hash table
5977   is created during the first matrix assembly. This hash table is
5978   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5979   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5980   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5981   supported by `MATMPIBAIJ` format only.
5982 
5983   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5984   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
5985 
5986   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5987   a zero location in the matrix
5988 
5989   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5990 
5991   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5992   zero row routines and thus improves performance for very large process counts.
5993 
5994   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5995   part of the matrix (since they should match the upper triangular part).
5996 
5997   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5998   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
5999   with finite difference schemes with non-periodic boundary conditions.
6000 
6001   Developer Note:
6002   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6003   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6004   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6005   not changed.
6006 
6007 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6008 @*/
6009 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6010 {
6011   PetscFunctionBegin;
6012   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6013   if (op > 0) {
6014     PetscValidLogicalCollectiveEnum(mat, op, 2);
6015     PetscValidLogicalCollectiveBool(mat, flg, 3);
6016   }
6017 
6018   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);
6019 
6020   switch (op) {
6021   case MAT_FORCE_DIAGONAL_ENTRIES:
6022     mat->force_diagonals = flg;
6023     PetscFunctionReturn(PETSC_SUCCESS);
6024   case MAT_NO_OFF_PROC_ENTRIES:
6025     mat->nooffprocentries = flg;
6026     PetscFunctionReturn(PETSC_SUCCESS);
6027   case MAT_SUBSET_OFF_PROC_ENTRIES:
6028     mat->assembly_subset = flg;
6029     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6030 #if !defined(PETSC_HAVE_MPIUNI)
6031       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6032 #endif
6033       mat->stash.first_assembly_done = PETSC_FALSE;
6034     }
6035     PetscFunctionReturn(PETSC_SUCCESS);
6036   case MAT_NO_OFF_PROC_ZERO_ROWS:
6037     mat->nooffproczerorows = flg;
6038     PetscFunctionReturn(PETSC_SUCCESS);
6039   case MAT_SPD:
6040     if (flg) {
6041       mat->spd                    = PETSC_BOOL3_TRUE;
6042       mat->symmetric              = PETSC_BOOL3_TRUE;
6043       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6044     } else {
6045       mat->spd = PETSC_BOOL3_FALSE;
6046     }
6047     break;
6048   case MAT_SYMMETRIC:
6049     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6050     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6051 #if !defined(PETSC_USE_COMPLEX)
6052     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6053 #endif
6054     break;
6055   case MAT_HERMITIAN:
6056     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6057     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6058 #if !defined(PETSC_USE_COMPLEX)
6059     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6060 #endif
6061     break;
6062   case MAT_STRUCTURALLY_SYMMETRIC:
6063     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6064     break;
6065   case MAT_SYMMETRY_ETERNAL:
6066     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");
6067     mat->symmetry_eternal = flg;
6068     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6069     break;
6070   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6071     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");
6072     mat->structural_symmetry_eternal = flg;
6073     break;
6074   case MAT_SPD_ETERNAL:
6075     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");
6076     mat->spd_eternal = flg;
6077     if (flg) {
6078       mat->structural_symmetry_eternal = PETSC_TRUE;
6079       mat->symmetry_eternal            = PETSC_TRUE;
6080     }
6081     break;
6082   case MAT_STRUCTURE_ONLY:
6083     mat->structure_only = flg;
6084     break;
6085   case MAT_SORTED_FULL:
6086     mat->sortedfull = flg;
6087     break;
6088   default:
6089     break;
6090   }
6091   PetscTryTypeMethod(mat, setoption, op, flg);
6092   PetscFunctionReturn(PETSC_SUCCESS);
6093 }
6094 
6095 /*@
6096   MatGetOption - Gets a parameter option that has been set for a matrix.
6097 
6098   Logically Collective
6099 
6100   Input Parameters:
6101 + mat - the matrix
6102 - op  - the option, this only responds to certain options, check the code for which ones
6103 
6104   Output Parameter:
6105 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6106 
6107   Level: intermediate
6108 
6109   Notes:
6110   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6111 
6112   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6113   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6114 
6115 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6116     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6117 @*/
6118 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6119 {
6120   PetscFunctionBegin;
6121   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6122   PetscValidType(mat, 1);
6123 
6124   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);
6125   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()");
6126 
6127   switch (op) {
6128   case MAT_NO_OFF_PROC_ENTRIES:
6129     *flg = mat->nooffprocentries;
6130     break;
6131   case MAT_NO_OFF_PROC_ZERO_ROWS:
6132     *flg = mat->nooffproczerorows;
6133     break;
6134   case MAT_SYMMETRIC:
6135     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6136     break;
6137   case MAT_HERMITIAN:
6138     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6139     break;
6140   case MAT_STRUCTURALLY_SYMMETRIC:
6141     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6142     break;
6143   case MAT_SPD:
6144     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6145     break;
6146   case MAT_SYMMETRY_ETERNAL:
6147     *flg = mat->symmetry_eternal;
6148     break;
6149   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6150     *flg = mat->symmetry_eternal;
6151     break;
6152   default:
6153     break;
6154   }
6155   PetscFunctionReturn(PETSC_SUCCESS);
6156 }
6157 
6158 /*@
6159   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6160   this routine retains the old nonzero structure.
6161 
6162   Logically Collective
6163 
6164   Input Parameter:
6165 . mat - the matrix
6166 
6167   Level: intermediate
6168 
6169   Note:
6170   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.
6171   See the Performance chapter of the users manual for information on preallocating matrices.
6172 
6173 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6174 @*/
6175 PetscErrorCode MatZeroEntries(Mat mat)
6176 {
6177   PetscFunctionBegin;
6178   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6179   PetscValidType(mat, 1);
6180   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6181   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");
6182   MatCheckPreallocated(mat, 1);
6183 
6184   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6185   PetscUseTypeMethod(mat, zeroentries);
6186   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6187   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6188   PetscFunctionReturn(PETSC_SUCCESS);
6189 }
6190 
6191 /*@
6192   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6193   of a set of rows and columns of a matrix.
6194 
6195   Collective
6196 
6197   Input Parameters:
6198 + mat     - the matrix
6199 . numRows - the number of rows/columns to zero
6200 . rows    - the global row indices
6201 . diag    - value put in the diagonal of the eliminated rows
6202 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6203 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6204 
6205   Level: intermediate
6206 
6207   Notes:
6208   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6209 
6210   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6211   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
6212 
6213   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6214   Krylov method to take advantage of the known solution on the zeroed rows.
6215 
6216   For the parallel case, all processes that share the matrix (i.e.,
6217   those in the communicator used for matrix creation) MUST call this
6218   routine, regardless of whether any rows being zeroed are owned by
6219   them.
6220 
6221   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6222   removes them from the nonzero pattern. The nonzero pattern of the matrix can still change if a nonzero needs to be inserted on a diagonal entry that was previously
6223   missing.
6224 
6225   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6226   list only rows local to itself).
6227 
6228   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6229 
6230 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6231           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6232 @*/
6233 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6234 {
6235   PetscFunctionBegin;
6236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6237   PetscValidType(mat, 1);
6238   if (numRows) PetscAssertPointer(rows, 3);
6239   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6240   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6241   MatCheckPreallocated(mat, 1);
6242 
6243   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6244   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6245   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6246   PetscFunctionReturn(PETSC_SUCCESS);
6247 }
6248 
6249 /*@
6250   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6251   of a set of rows and columns of a matrix.
6252 
6253   Collective
6254 
6255   Input Parameters:
6256 + mat  - the matrix
6257 . is   - the rows to zero
6258 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6259 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6260 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6261 
6262   Level: intermediate
6263 
6264   Note:
6265   See `MatZeroRowsColumns()` for details on how this routine operates.
6266 
6267 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6268           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6269 @*/
6270 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6271 {
6272   PetscInt        numRows;
6273   const PetscInt *rows;
6274 
6275   PetscFunctionBegin;
6276   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6277   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6278   PetscValidType(mat, 1);
6279   PetscValidType(is, 2);
6280   PetscCall(ISGetLocalSize(is, &numRows));
6281   PetscCall(ISGetIndices(is, &rows));
6282   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6283   PetscCall(ISRestoreIndices(is, &rows));
6284   PetscFunctionReturn(PETSC_SUCCESS);
6285 }
6286 
6287 /*@
6288   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6289   of a set of rows of a matrix.
6290 
6291   Collective
6292 
6293   Input Parameters:
6294 + mat     - the matrix
6295 . numRows - the number of rows to zero
6296 . rows    - the global row indices
6297 . diag    - value put in the diagonal of the zeroed rows
6298 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6299 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6300 
6301   Level: intermediate
6302 
6303   Notes:
6304   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6305 
6306   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6307 
6308   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6309   Krylov method to take advantage of the known solution on the zeroed rows.
6310 
6311   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)
6312   from the matrix.
6313 
6314   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6315   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
6316   formats this does not alter the nonzero structure.
6317 
6318   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6319   of the matrix is not changed the values are
6320   merely zeroed.
6321 
6322   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6323   formats can optionally remove the main diagonal entry from the
6324   nonzero structure as well, by passing 0.0 as the final argument).
6325 
6326   For the parallel case, all processes that share the matrix (i.e.,
6327   those in the communicator used for matrix creation) MUST call this
6328   routine, regardless of whether any rows being zeroed are owned by
6329   them.
6330 
6331   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6332   list only rows local to itself).
6333 
6334   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6335   owns that are to be zeroed. This saves a global synchronization in the implementation.
6336 
6337 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6338           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6339 @*/
6340 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6341 {
6342   PetscFunctionBegin;
6343   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6344   PetscValidType(mat, 1);
6345   if (numRows) PetscAssertPointer(rows, 3);
6346   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6347   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6348   MatCheckPreallocated(mat, 1);
6349 
6350   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6351   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6352   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6353   PetscFunctionReturn(PETSC_SUCCESS);
6354 }
6355 
6356 /*@
6357   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6358   of a set of rows of a matrix.
6359 
6360   Collective
6361 
6362   Input Parameters:
6363 + mat  - the matrix
6364 . is   - index set of rows to remove (if `NULL` then no row is removed)
6365 . diag - value put in all diagonals of eliminated rows
6366 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6367 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6368 
6369   Level: intermediate
6370 
6371   Note:
6372   See `MatZeroRows()` for details on how this routine operates.
6373 
6374 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6375           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6376 @*/
6377 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6378 {
6379   PetscInt        numRows = 0;
6380   const PetscInt *rows    = NULL;
6381 
6382   PetscFunctionBegin;
6383   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6384   PetscValidType(mat, 1);
6385   if (is) {
6386     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6387     PetscCall(ISGetLocalSize(is, &numRows));
6388     PetscCall(ISGetIndices(is, &rows));
6389   }
6390   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6391   if (is) PetscCall(ISRestoreIndices(is, &rows));
6392   PetscFunctionReturn(PETSC_SUCCESS);
6393 }
6394 
6395 /*@
6396   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6397   of a set of rows of a matrix. These rows must be local to the process.
6398 
6399   Collective
6400 
6401   Input Parameters:
6402 + mat     - the matrix
6403 . numRows - the number of rows to remove
6404 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6405 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6406 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6407 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6408 
6409   Level: intermediate
6410 
6411   Notes:
6412   See `MatZeroRows()` for details on how this routine operates.
6413 
6414   The grid coordinates are across the entire grid, not just the local portion
6415 
6416   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6417   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6418   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6419   `DM_BOUNDARY_PERIODIC` boundary type.
6420 
6421   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
6422   a single value per point) you can skip filling those indices.
6423 
6424   Fortran Note:
6425   `idxm` and `idxn` should be declared as
6426 $     MatStencil idxm(4, m)
6427   and the values inserted using
6428 .vb
6429     idxm(MatStencil_i, 1) = i
6430     idxm(MatStencil_j, 1) = j
6431     idxm(MatStencil_k, 1) = k
6432     idxm(MatStencil_c, 1) = c
6433    etc
6434 .ve
6435 
6436 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6437           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6438 @*/
6439 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6440 {
6441   PetscInt  dim    = mat->stencil.dim;
6442   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6443   PetscInt *dims   = mat->stencil.dims + 1;
6444   PetscInt *starts = mat->stencil.starts;
6445   PetscInt *dxm    = (PetscInt *)rows;
6446   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6447 
6448   PetscFunctionBegin;
6449   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6450   PetscValidType(mat, 1);
6451   if (numRows) PetscAssertPointer(rows, 3);
6452 
6453   PetscCall(PetscMalloc1(numRows, &jdxm));
6454   for (i = 0; i < numRows; ++i) {
6455     /* Skip unused dimensions (they are ordered k, j, i, c) */
6456     for (j = 0; j < 3 - sdim; ++j) dxm++;
6457     /* Local index in X dir */
6458     tmp = *dxm++ - starts[0];
6459     /* Loop over remaining dimensions */
6460     for (j = 0; j < dim - 1; ++j) {
6461       /* If nonlocal, set index to be negative */
6462       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6463       /* Update local index */
6464       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6465     }
6466     /* Skip component slot if necessary */
6467     if (mat->stencil.noc) dxm++;
6468     /* Local row number */
6469     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6470   }
6471   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6472   PetscCall(PetscFree(jdxm));
6473   PetscFunctionReturn(PETSC_SUCCESS);
6474 }
6475 
6476 /*@
6477   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6478   of a set of rows and columns of a matrix.
6479 
6480   Collective
6481 
6482   Input Parameters:
6483 + mat     - the matrix
6484 . numRows - the number of rows/columns to remove
6485 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6486 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6487 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6488 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6489 
6490   Level: intermediate
6491 
6492   Notes:
6493   See `MatZeroRowsColumns()` for details on how this routine operates.
6494 
6495   The grid coordinates are across the entire grid, not just the local portion
6496 
6497   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6498   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6499   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6500   `DM_BOUNDARY_PERIODIC` boundary type.
6501 
6502   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
6503   a single value per point) you can skip filling those indices.
6504 
6505   Fortran Note:
6506   `idxm` and `idxn` should be declared as
6507 $     MatStencil idxm(4, m)
6508   and the values inserted using
6509 .vb
6510     idxm(MatStencil_i, 1) = i
6511     idxm(MatStencil_j, 1) = j
6512     idxm(MatStencil_k, 1) = k
6513     idxm(MatStencil_c, 1) = c
6514     etc
6515 .ve
6516 
6517 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6518           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6519 @*/
6520 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6521 {
6522   PetscInt  dim    = mat->stencil.dim;
6523   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6524   PetscInt *dims   = mat->stencil.dims + 1;
6525   PetscInt *starts = mat->stencil.starts;
6526   PetscInt *dxm    = (PetscInt *)rows;
6527   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6528 
6529   PetscFunctionBegin;
6530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6531   PetscValidType(mat, 1);
6532   if (numRows) PetscAssertPointer(rows, 3);
6533 
6534   PetscCall(PetscMalloc1(numRows, &jdxm));
6535   for (i = 0; i < numRows; ++i) {
6536     /* Skip unused dimensions (they are ordered k, j, i, c) */
6537     for (j = 0; j < 3 - sdim; ++j) dxm++;
6538     /* Local index in X dir */
6539     tmp = *dxm++ - starts[0];
6540     /* Loop over remaining dimensions */
6541     for (j = 0; j < dim - 1; ++j) {
6542       /* If nonlocal, set index to be negative */
6543       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6544       /* Update local index */
6545       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6546     }
6547     /* Skip component slot if necessary */
6548     if (mat->stencil.noc) dxm++;
6549     /* Local row number */
6550     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6551   }
6552   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6553   PetscCall(PetscFree(jdxm));
6554   PetscFunctionReturn(PETSC_SUCCESS);
6555 }
6556 
6557 /*@C
6558   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6559   of a set of rows of a matrix; using local numbering of rows.
6560 
6561   Collective
6562 
6563   Input Parameters:
6564 + mat     - the matrix
6565 . numRows - the number of rows to remove
6566 . rows    - the local row indices
6567 . diag    - value put in all diagonals of eliminated rows
6568 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6569 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6570 
6571   Level: intermediate
6572 
6573   Notes:
6574   Before calling `MatZeroRowsLocal()`, the user must first set the
6575   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6576 
6577   See `MatZeroRows()` for details on how this routine operates.
6578 
6579 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6580           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6581 @*/
6582 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6583 {
6584   PetscFunctionBegin;
6585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6586   PetscValidType(mat, 1);
6587   if (numRows) PetscAssertPointer(rows, 3);
6588   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6589   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6590   MatCheckPreallocated(mat, 1);
6591 
6592   if (mat->ops->zerorowslocal) {
6593     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6594   } else {
6595     IS              is, newis;
6596     const PetscInt *newRows;
6597 
6598     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6599     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6600     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6601     PetscCall(ISGetIndices(newis, &newRows));
6602     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6603     PetscCall(ISRestoreIndices(newis, &newRows));
6604     PetscCall(ISDestroy(&newis));
6605     PetscCall(ISDestroy(&is));
6606   }
6607   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6608   PetscFunctionReturn(PETSC_SUCCESS);
6609 }
6610 
6611 /*@
6612   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6613   of a set of rows of a matrix; using local numbering of rows.
6614 
6615   Collective
6616 
6617   Input Parameters:
6618 + mat  - the matrix
6619 . is   - index set of rows to remove
6620 . diag - value put in all diagonals of eliminated rows
6621 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6622 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6623 
6624   Level: intermediate
6625 
6626   Notes:
6627   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6628   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6629 
6630   See `MatZeroRows()` for details on how this routine operates.
6631 
6632 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6633           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6634 @*/
6635 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6636 {
6637   PetscInt        numRows;
6638   const PetscInt *rows;
6639 
6640   PetscFunctionBegin;
6641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6642   PetscValidType(mat, 1);
6643   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6645   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6646   MatCheckPreallocated(mat, 1);
6647 
6648   PetscCall(ISGetLocalSize(is, &numRows));
6649   PetscCall(ISGetIndices(is, &rows));
6650   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6651   PetscCall(ISRestoreIndices(is, &rows));
6652   PetscFunctionReturn(PETSC_SUCCESS);
6653 }
6654 
6655 /*@
6656   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6657   of a set of rows and columns of a matrix; using local numbering of rows.
6658 
6659   Collective
6660 
6661   Input Parameters:
6662 + mat     - the matrix
6663 . numRows - the number of rows to remove
6664 . rows    - the global row indices
6665 . diag    - value put in all diagonals of eliminated rows
6666 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6667 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6668 
6669   Level: intermediate
6670 
6671   Notes:
6672   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6673   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6674 
6675   See `MatZeroRowsColumns()` for details on how this routine operates.
6676 
6677 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6678           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6679 @*/
6680 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6681 {
6682   IS              is, newis;
6683   const PetscInt *newRows;
6684 
6685   PetscFunctionBegin;
6686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6687   PetscValidType(mat, 1);
6688   if (numRows) PetscAssertPointer(rows, 3);
6689   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6690   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6691   MatCheckPreallocated(mat, 1);
6692 
6693   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6694   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6695   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6696   PetscCall(ISGetIndices(newis, &newRows));
6697   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6698   PetscCall(ISRestoreIndices(newis, &newRows));
6699   PetscCall(ISDestroy(&newis));
6700   PetscCall(ISDestroy(&is));
6701   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6702   PetscFunctionReturn(PETSC_SUCCESS);
6703 }
6704 
6705 /*@
6706   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6707   of a set of rows and columns of a matrix; using local numbering of rows.
6708 
6709   Collective
6710 
6711   Input Parameters:
6712 + mat  - the matrix
6713 . is   - index set of rows to remove
6714 . diag - value put in all diagonals of eliminated rows
6715 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6716 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6717 
6718   Level: intermediate
6719 
6720   Notes:
6721   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6722   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6723 
6724   See `MatZeroRowsColumns()` for details on how this routine operates.
6725 
6726 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6727           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6728 @*/
6729 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6730 {
6731   PetscInt        numRows;
6732   const PetscInt *rows;
6733 
6734   PetscFunctionBegin;
6735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6736   PetscValidType(mat, 1);
6737   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6738   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6739   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6740   MatCheckPreallocated(mat, 1);
6741 
6742   PetscCall(ISGetLocalSize(is, &numRows));
6743   PetscCall(ISGetIndices(is, &rows));
6744   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6745   PetscCall(ISRestoreIndices(is, &rows));
6746   PetscFunctionReturn(PETSC_SUCCESS);
6747 }
6748 
6749 /*@C
6750   MatGetSize - Returns the numbers of rows and columns in a matrix.
6751 
6752   Not Collective
6753 
6754   Input Parameter:
6755 . mat - the matrix
6756 
6757   Output Parameters:
6758 + m - the number of global rows
6759 - n - the number of global columns
6760 
6761   Level: beginner
6762 
6763   Note:
6764   Both output parameters can be `NULL` on input.
6765 
6766 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6767 @*/
6768 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6769 {
6770   PetscFunctionBegin;
6771   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6772   if (m) *m = mat->rmap->N;
6773   if (n) *n = mat->cmap->N;
6774   PetscFunctionReturn(PETSC_SUCCESS);
6775 }
6776 
6777 /*@C
6778   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6779   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6780 
6781   Not Collective
6782 
6783   Input Parameter:
6784 . mat - the matrix
6785 
6786   Output Parameters:
6787 + m - the number of local rows, use `NULL` to not obtain this value
6788 - n - the number of local columns, use `NULL` to not obtain this value
6789 
6790   Level: beginner
6791 
6792 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6793 @*/
6794 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6795 {
6796   PetscFunctionBegin;
6797   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6798   if (m) PetscAssertPointer(m, 2);
6799   if (n) PetscAssertPointer(n, 3);
6800   if (m) *m = mat->rmap->n;
6801   if (n) *n = mat->cmap->n;
6802   PetscFunctionReturn(PETSC_SUCCESS);
6803 }
6804 
6805 /*@
6806   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6807   vector one multiplies this matrix by that are owned by this processor.
6808 
6809   Not Collective, unless matrix has not been allocated, then collective
6810 
6811   Input Parameter:
6812 . mat - the matrix
6813 
6814   Output Parameters:
6815 + m - the global index of the first local column, use `NULL` to not obtain this value
6816 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6817 
6818   Level: developer
6819 
6820   Notes:
6821   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6822 
6823   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6824   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6825 
6826   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6827   the local values in the matrix.
6828 
6829   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6830   Layouts](sec_matlayout) for details on matrix layouts.
6831 
6832 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6833           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6834 @*/
6835 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6836 {
6837   PetscFunctionBegin;
6838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6839   PetscValidType(mat, 1);
6840   if (m) PetscAssertPointer(m, 2);
6841   if (n) PetscAssertPointer(n, 3);
6842   MatCheckPreallocated(mat, 1);
6843   if (m) *m = mat->cmap->rstart;
6844   if (n) *n = mat->cmap->rend;
6845   PetscFunctionReturn(PETSC_SUCCESS);
6846 }
6847 
6848 /*@C
6849   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6850   this MPI process.
6851 
6852   Not Collective
6853 
6854   Input Parameter:
6855 . mat - the matrix
6856 
6857   Output Parameters:
6858 + m - the global index of the first local row, use `NULL` to not obtain this value
6859 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6860 
6861   Level: beginner
6862 
6863   Notes:
6864   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6865 
6866   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6867   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6868 
6869   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6870   the local values in the matrix.
6871 
6872   The high argument is one more than the last element stored locally.
6873 
6874   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6875   would contain the result of a matrix vector product with this matrix. See [Matrix
6876   Layouts](sec_matlayout) for details on matrix layouts.
6877 
6878 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6879           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6880 @*/
6881 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6882 {
6883   PetscFunctionBegin;
6884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6885   PetscValidType(mat, 1);
6886   if (m) PetscAssertPointer(m, 2);
6887   if (n) PetscAssertPointer(n, 3);
6888   MatCheckPreallocated(mat, 1);
6889   if (m) *m = mat->rmap->rstart;
6890   if (n) *n = mat->rmap->rend;
6891   PetscFunctionReturn(PETSC_SUCCESS);
6892 }
6893 
6894 /*@C
6895   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6896   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6897 
6898   Not Collective, unless matrix has not been allocated
6899 
6900   Input Parameter:
6901 . mat - the matrix
6902 
6903   Output Parameter:
6904 . ranges - start of each processors portion plus one more than the total length at the end
6905 
6906   Level: beginner
6907 
6908   Notes:
6909   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6910 
6911   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6912   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6913 
6914   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6915   the local values in the matrix.
6916 
6917   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6918   would contain the result of a matrix vector product with this matrix. See [Matrix
6919   Layouts](sec_matlayout) for details on matrix layouts.
6920 
6921 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6922           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6923           `DMDAGetGhostCorners()`, `DM`
6924 @*/
6925 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6926 {
6927   PetscFunctionBegin;
6928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6929   PetscValidType(mat, 1);
6930   MatCheckPreallocated(mat, 1);
6931   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6932   PetscFunctionReturn(PETSC_SUCCESS);
6933 }
6934 
6935 /*@C
6936   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6937   vector one multiplies this vector by that are owned by each processor.
6938 
6939   Not Collective, unless matrix has not been allocated
6940 
6941   Input Parameter:
6942 . mat - the matrix
6943 
6944   Output Parameter:
6945 . ranges - start of each processors portion plus one more than the total length at the end
6946 
6947   Level: beginner
6948 
6949   Notes:
6950   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6951 
6952   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6953   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6954 
6955   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6956   the local values in the matrix.
6957 
6958   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6959   Layouts](sec_matlayout) for details on matrix layouts.
6960 
6961 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6962           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6963           `DMDAGetGhostCorners()`, `DM`
6964 @*/
6965 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6966 {
6967   PetscFunctionBegin;
6968   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6969   PetscValidType(mat, 1);
6970   MatCheckPreallocated(mat, 1);
6971   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6972   PetscFunctionReturn(PETSC_SUCCESS);
6973 }
6974 
6975 /*@C
6976   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6977 
6978   Not Collective
6979 
6980   Input Parameter:
6981 . A - matrix
6982 
6983   Output Parameters:
6984 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6985 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6986 
6987   Level: intermediate
6988 
6989   Note:
6990   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6991   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6992   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6993   details on matrix layouts.
6994 
6995 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumns()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
6996 @*/
6997 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6998 {
6999   PetscErrorCode (*f)(Mat, IS *, IS *);
7000 
7001   PetscFunctionBegin;
7002   MatCheckPreallocated(A, 1);
7003   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7004   if (f) {
7005     PetscCall((*f)(A, rows, cols));
7006   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7007     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7008     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7009   }
7010   PetscFunctionReturn(PETSC_SUCCESS);
7011 }
7012 
7013 /*@C
7014   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7015   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7016   to complete the factorization.
7017 
7018   Collective
7019 
7020   Input Parameters:
7021 + fact - the factorized matrix obtained with `MatGetFactor()`
7022 . mat  - the matrix
7023 . row  - row permutation
7024 . col  - column permutation
7025 - info - structure containing
7026 .vb
7027       levels - number of levels of fill.
7028       expected fill - as ratio of original fill.
7029       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7030                 missing diagonal entries)
7031 .ve
7032 
7033   Level: developer
7034 
7035   Notes:
7036   See [Matrix Factorization](sec_matfactor) for additional information.
7037 
7038   Most users should employ the `KSP` interface for linear solvers
7039   instead of working directly with matrix algebra routines such as this.
7040   See, e.g., `KSPCreate()`.
7041 
7042   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7043 
7044   Developer Note:
7045   The Fortran interface is not autogenerated as the
7046   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7047 
7048 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7049           `MatGetOrdering()`, `MatFactorInfo`
7050 @*/
7051 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7052 {
7053   PetscFunctionBegin;
7054   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7055   PetscValidType(mat, 2);
7056   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7057   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7058   PetscAssertPointer(info, 5);
7059   PetscAssertPointer(fact, 1);
7060   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7061   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7062   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7063   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7064   MatCheckPreallocated(mat, 2);
7065 
7066   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7067   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7068   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7069   PetscFunctionReturn(PETSC_SUCCESS);
7070 }
7071 
7072 /*@C
7073   MatICCFactorSymbolic - Performs symbolic incomplete
7074   Cholesky factorization for a symmetric matrix.  Use
7075   `MatCholeskyFactorNumeric()` to complete the factorization.
7076 
7077   Collective
7078 
7079   Input Parameters:
7080 + fact - the factorized matrix obtained with `MatGetFactor()`
7081 . mat  - the matrix to be factored
7082 . perm - row and column permutation
7083 - info - structure containing
7084 .vb
7085       levels - number of levels of fill.
7086       expected fill - as ratio of original fill.
7087 .ve
7088 
7089   Level: developer
7090 
7091   Notes:
7092   Most users should employ the `KSP` interface for linear solvers
7093   instead of working directly with matrix algebra routines such as this.
7094   See, e.g., `KSPCreate()`.
7095 
7096   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7097 
7098   Developer Note:
7099   The Fortran interface is not autogenerated as the
7100   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7101 
7102 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7103 @*/
7104 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7105 {
7106   PetscFunctionBegin;
7107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7108   PetscValidType(mat, 2);
7109   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7110   PetscAssertPointer(info, 4);
7111   PetscAssertPointer(fact, 1);
7112   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7113   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7114   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7115   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7116   MatCheckPreallocated(mat, 2);
7117 
7118   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7119   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7120   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7121   PetscFunctionReturn(PETSC_SUCCESS);
7122 }
7123 
7124 /*@C
7125   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7126   points to an array of valid matrices, they may be reused to store the new
7127   submatrices.
7128 
7129   Collective
7130 
7131   Input Parameters:
7132 + mat   - the matrix
7133 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7134 . irow  - index set of rows to extract
7135 . icol  - index set of columns to extract
7136 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7137 
7138   Output Parameter:
7139 . submat - the array of submatrices
7140 
7141   Level: advanced
7142 
7143   Notes:
7144   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7145   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7146   to extract a parallel submatrix.
7147 
7148   Some matrix types place restrictions on the row and column
7149   indices, such as that they be sorted or that they be equal to each other.
7150 
7151   The index sets may not have duplicate entries.
7152 
7153   When extracting submatrices from a parallel matrix, each processor can
7154   form a different submatrix by setting the rows and columns of its
7155   individual index sets according to the local submatrix desired.
7156 
7157   When finished using the submatrices, the user should destroy
7158   them with `MatDestroySubMatrices()`.
7159 
7160   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7161   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7162 
7163   This routine creates the matrices in submat; you should NOT create them before
7164   calling it. It also allocates the array of matrix pointers submat.
7165 
7166   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7167   request one row/column in a block, they must request all rows/columns that are in
7168   that block. For example, if the block size is 2 you cannot request just row 0 and
7169   column 0.
7170 
7171   Fortran Note:
7172   The Fortran interface is slightly different from that given below; it
7173   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7174 
7175 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7176 @*/
7177 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7178 {
7179   PetscInt  i;
7180   PetscBool eq;
7181 
7182   PetscFunctionBegin;
7183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7184   PetscValidType(mat, 1);
7185   if (n) {
7186     PetscAssertPointer(irow, 3);
7187     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7188     PetscAssertPointer(icol, 4);
7189     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7190   }
7191   PetscAssertPointer(submat, 6);
7192   if (n && scall == MAT_REUSE_MATRIX) {
7193     PetscAssertPointer(*submat, 6);
7194     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7195   }
7196   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7197   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7198   MatCheckPreallocated(mat, 1);
7199   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7200   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7201   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7202   for (i = 0; i < n; i++) {
7203     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7204     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7205     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7206 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7207     if (mat->boundtocpu && mat->bindingpropagates) {
7208       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7209       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7210     }
7211 #endif
7212   }
7213   PetscFunctionReturn(PETSC_SUCCESS);
7214 }
7215 
7216 /*@C
7217   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7218 
7219   Collective
7220 
7221   Input Parameters:
7222 + mat   - the matrix
7223 . n     - the number of submatrixes to be extracted
7224 . irow  - index set of rows to extract
7225 . icol  - index set of columns to extract
7226 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7227 
7228   Output Parameter:
7229 . submat - the array of submatrices
7230 
7231   Level: advanced
7232 
7233   Note:
7234   This is used by `PCGASM`
7235 
7236 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7237 @*/
7238 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7239 {
7240   PetscInt  i;
7241   PetscBool eq;
7242 
7243   PetscFunctionBegin;
7244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7245   PetscValidType(mat, 1);
7246   if (n) {
7247     PetscAssertPointer(irow, 3);
7248     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7249     PetscAssertPointer(icol, 4);
7250     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7251   }
7252   PetscAssertPointer(submat, 6);
7253   if (n && scall == MAT_REUSE_MATRIX) {
7254     PetscAssertPointer(*submat, 6);
7255     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7256   }
7257   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7258   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7259   MatCheckPreallocated(mat, 1);
7260 
7261   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7262   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7263   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7264   for (i = 0; i < n; i++) {
7265     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7266     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7267   }
7268   PetscFunctionReturn(PETSC_SUCCESS);
7269 }
7270 
7271 /*@C
7272   MatDestroyMatrices - Destroys an array of matrices.
7273 
7274   Collective
7275 
7276   Input Parameters:
7277 + n   - the number of local matrices
7278 - mat - the matrices (this is a pointer to the array of matrices)
7279 
7280   Level: advanced
7281 
7282   Note:
7283   Frees not only the matrices, but also the array that contains the matrices
7284 
7285   Fortran Note:
7286   This does not free the array.
7287 
7288 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7289 @*/
7290 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7291 {
7292   PetscInt i;
7293 
7294   PetscFunctionBegin;
7295   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7296   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7297   PetscAssertPointer(mat, 2);
7298 
7299   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7300 
7301   /* memory is allocated even if n = 0 */
7302   PetscCall(PetscFree(*mat));
7303   PetscFunctionReturn(PETSC_SUCCESS);
7304 }
7305 
7306 /*@C
7307   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7308 
7309   Collective
7310 
7311   Input Parameters:
7312 + n   - the number of local matrices
7313 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7314                        sequence of `MatCreateSubMatrices()`)
7315 
7316   Level: advanced
7317 
7318   Note:
7319   Frees not only the matrices, but also the array that contains the matrices
7320 
7321   Fortran Note:
7322   This does not free the array.
7323 
7324 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7325 @*/
7326 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7327 {
7328   Mat mat0;
7329 
7330   PetscFunctionBegin;
7331   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7332   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7333   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7334   PetscAssertPointer(mat, 2);
7335 
7336   mat0 = (*mat)[0];
7337   if (mat0 && mat0->ops->destroysubmatrices) {
7338     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7339   } else {
7340     PetscCall(MatDestroyMatrices(n, mat));
7341   }
7342   PetscFunctionReturn(PETSC_SUCCESS);
7343 }
7344 
7345 /*@
7346   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7347 
7348   Collective
7349 
7350   Input Parameter:
7351 . mat - the matrix
7352 
7353   Output Parameter:
7354 . matstruct - the sequential matrix with the nonzero structure of `mat`
7355 
7356   Level: developer
7357 
7358 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7359 @*/
7360 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7361 {
7362   PetscFunctionBegin;
7363   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7364   PetscAssertPointer(matstruct, 2);
7365 
7366   PetscValidType(mat, 1);
7367   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7368   MatCheckPreallocated(mat, 1);
7369 
7370   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7371   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7372   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7373   PetscFunctionReturn(PETSC_SUCCESS);
7374 }
7375 
7376 /*@C
7377   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7378 
7379   Collective
7380 
7381   Input Parameter:
7382 . mat - the matrix
7383 
7384   Level: advanced
7385 
7386   Note:
7387   This is not needed, one can just call `MatDestroy()`
7388 
7389 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7390 @*/
7391 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7392 {
7393   PetscFunctionBegin;
7394   PetscAssertPointer(mat, 1);
7395   PetscCall(MatDestroy(mat));
7396   PetscFunctionReturn(PETSC_SUCCESS);
7397 }
7398 
7399 /*@
7400   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7401   replaces the index sets by larger ones that represent submatrices with
7402   additional overlap.
7403 
7404   Collective
7405 
7406   Input Parameters:
7407 + mat - the matrix
7408 . n   - the number of index sets
7409 . is  - the array of index sets (these index sets will changed during the call)
7410 - ov  - the additional overlap requested
7411 
7412   Options Database Key:
7413 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7414 
7415   Level: developer
7416 
7417   Note:
7418   The computed overlap preserves the matrix block sizes when the blocks are square.
7419   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7420   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7421 
7422 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7423 @*/
7424 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7425 {
7426   PetscInt i, bs, cbs;
7427 
7428   PetscFunctionBegin;
7429   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7430   PetscValidType(mat, 1);
7431   PetscValidLogicalCollectiveInt(mat, n, 2);
7432   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7433   if (n) {
7434     PetscAssertPointer(is, 3);
7435     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7436   }
7437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7439   MatCheckPreallocated(mat, 1);
7440 
7441   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7442   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7443   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7444   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7445   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7446   if (bs == cbs) {
7447     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7448   }
7449   PetscFunctionReturn(PETSC_SUCCESS);
7450 }
7451 
7452 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7453 
7454 /*@
7455   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7456   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7457   additional overlap.
7458 
7459   Collective
7460 
7461   Input Parameters:
7462 + mat - the matrix
7463 . n   - the number of index sets
7464 . is  - the array of index sets (these index sets will changed during the call)
7465 - ov  - the additional overlap requested
7466 
7467   `   Options Database Key:
7468 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7469 
7470   Level: developer
7471 
7472 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7473 @*/
7474 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7475 {
7476   PetscInt i;
7477 
7478   PetscFunctionBegin;
7479   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7480   PetscValidType(mat, 1);
7481   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7482   if (n) {
7483     PetscAssertPointer(is, 3);
7484     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7485   }
7486   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7487   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7488   MatCheckPreallocated(mat, 1);
7489   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7490   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7491   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7492   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7493   PetscFunctionReturn(PETSC_SUCCESS);
7494 }
7495 
7496 /*@
7497   MatGetBlockSize - Returns the matrix block size.
7498 
7499   Not Collective
7500 
7501   Input Parameter:
7502 . mat - the matrix
7503 
7504   Output Parameter:
7505 . bs - block size
7506 
7507   Level: intermediate
7508 
7509   Notes:
7510   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7511 
7512   If the block size has not been set yet this routine returns 1.
7513 
7514 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7515 @*/
7516 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7517 {
7518   PetscFunctionBegin;
7519   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7520   PetscAssertPointer(bs, 2);
7521   *bs = PetscAbs(mat->rmap->bs);
7522   PetscFunctionReturn(PETSC_SUCCESS);
7523 }
7524 
7525 /*@
7526   MatGetBlockSizes - Returns the matrix block row and column sizes.
7527 
7528   Not Collective
7529 
7530   Input Parameter:
7531 . mat - the matrix
7532 
7533   Output Parameters:
7534 + rbs - row block size
7535 - cbs - column block size
7536 
7537   Level: intermediate
7538 
7539   Notes:
7540   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7541   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7542 
7543   If a block size has not been set yet this routine returns 1.
7544 
7545 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7546 @*/
7547 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7548 {
7549   PetscFunctionBegin;
7550   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7551   if (rbs) PetscAssertPointer(rbs, 2);
7552   if (cbs) PetscAssertPointer(cbs, 3);
7553   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7554   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7555   PetscFunctionReturn(PETSC_SUCCESS);
7556 }
7557 
7558 /*@
7559   MatSetBlockSize - Sets the matrix block size.
7560 
7561   Logically Collective
7562 
7563   Input Parameters:
7564 + mat - the matrix
7565 - bs  - block size
7566 
7567   Level: intermediate
7568 
7569   Notes:
7570   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7571   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7572 
7573   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7574   is compatible with the matrix local sizes.
7575 
7576 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7577 @*/
7578 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7579 {
7580   PetscFunctionBegin;
7581   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7582   PetscValidLogicalCollectiveInt(mat, bs, 2);
7583   PetscCall(MatSetBlockSizes(mat, bs, bs));
7584   PetscFunctionReturn(PETSC_SUCCESS);
7585 }
7586 
7587 typedef struct {
7588   PetscInt         n;
7589   IS              *is;
7590   Mat             *mat;
7591   PetscObjectState nonzerostate;
7592   Mat              C;
7593 } EnvelopeData;
7594 
7595 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7596 {
7597   EnvelopeData *edata = (EnvelopeData *)ptr;
7598 
7599   PetscFunctionBegin;
7600   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7601   PetscCall(PetscFree(edata->is));
7602   PetscCall(PetscFree(edata));
7603   PetscFunctionReturn(PETSC_SUCCESS);
7604 }
7605 
7606 /*@
7607   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7608   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7609 
7610   Collective
7611 
7612   Input Parameter:
7613 . mat - the matrix
7614 
7615   Level: intermediate
7616 
7617   Notes:
7618   There can be zeros within the blocks
7619 
7620   The blocks can overlap between processes, including laying on more than two processes
7621 
7622 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7623 @*/
7624 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7625 {
7626   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7627   PetscInt          *diag, *odiag, sc;
7628   VecScatter         scatter;
7629   PetscScalar       *seqv;
7630   const PetscScalar *parv;
7631   const PetscInt    *ia, *ja;
7632   PetscBool          set, flag, done;
7633   Mat                AA = mat, A;
7634   MPI_Comm           comm;
7635   PetscMPIInt        rank, size, tag;
7636   MPI_Status         status;
7637   PetscContainer     container;
7638   EnvelopeData      *edata;
7639   Vec                seq, par;
7640   IS                 isglobal;
7641 
7642   PetscFunctionBegin;
7643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7644   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7645   if (!set || !flag) {
7646     /* TODO: only needs nonzero structure of transpose */
7647     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7648     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7649   }
7650   PetscCall(MatAIJGetLocalMat(AA, &A));
7651   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7652   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7653 
7654   PetscCall(MatGetLocalSize(mat, &n, NULL));
7655   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7656   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7657   PetscCallMPI(MPI_Comm_size(comm, &size));
7658   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7659 
7660   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7661 
7662   if (rank > 0) {
7663     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7664     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7665   }
7666   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7667   for (i = 0; i < n; i++) {
7668     env = PetscMax(env, ja[ia[i + 1] - 1]);
7669     II  = rstart + i;
7670     if (env == II) {
7671       starts[lblocks]  = tbs;
7672       sizes[lblocks++] = 1 + II - tbs;
7673       tbs              = 1 + II;
7674     }
7675   }
7676   if (rank < size - 1) {
7677     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7678     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7679   }
7680 
7681   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7682   if (!set || !flag) PetscCall(MatDestroy(&AA));
7683   PetscCall(MatDestroy(&A));
7684 
7685   PetscCall(PetscNew(&edata));
7686   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7687   edata->n = lblocks;
7688   /* create IS needed for extracting blocks from the original matrix */
7689   PetscCall(PetscMalloc1(lblocks, &edata->is));
7690   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7691 
7692   /* Create the resulting inverse matrix structure with preallocation information */
7693   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7694   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7695   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7696   PetscCall(MatSetType(edata->C, MATAIJ));
7697 
7698   /* Communicate the start and end of each row, from each block to the correct rank */
7699   /* TODO: Use PetscSF instead of VecScatter */
7700   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7701   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7702   PetscCall(VecGetArrayWrite(seq, &seqv));
7703   for (PetscInt i = 0; i < lblocks; i++) {
7704     for (PetscInt j = 0; j < sizes[i]; j++) {
7705       seqv[cnt]     = starts[i];
7706       seqv[cnt + 1] = starts[i] + sizes[i];
7707       cnt += 2;
7708     }
7709   }
7710   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7711   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7712   sc -= cnt;
7713   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7714   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7715   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7716   PetscCall(ISDestroy(&isglobal));
7717   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7718   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7719   PetscCall(VecScatterDestroy(&scatter));
7720   PetscCall(VecDestroy(&seq));
7721   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7722   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7723   PetscCall(VecGetArrayRead(par, &parv));
7724   cnt = 0;
7725   PetscCall(MatGetSize(mat, NULL, &n));
7726   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7727     PetscInt start, end, d = 0, od = 0;
7728 
7729     start = (PetscInt)PetscRealPart(parv[cnt]);
7730     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7731     cnt += 2;
7732 
7733     if (start < cstart) {
7734       od += cstart - start + n - cend;
7735       d += cend - cstart;
7736     } else if (start < cend) {
7737       od += n - cend;
7738       d += cend - start;
7739     } else od += n - start;
7740     if (end <= cstart) {
7741       od -= cstart - end + n - cend;
7742       d -= cend - cstart;
7743     } else if (end < cend) {
7744       od -= n - cend;
7745       d -= cend - end;
7746     } else od -= n - end;
7747 
7748     odiag[i] = od;
7749     diag[i]  = d;
7750   }
7751   PetscCall(VecRestoreArrayRead(par, &parv));
7752   PetscCall(VecDestroy(&par));
7753   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7754   PetscCall(PetscFree2(diag, odiag));
7755   PetscCall(PetscFree2(sizes, starts));
7756 
7757   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7758   PetscCall(PetscContainerSetPointer(container, edata));
7759   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7760   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7761   PetscCall(PetscObjectDereference((PetscObject)container));
7762   PetscFunctionReturn(PETSC_SUCCESS);
7763 }
7764 
7765 /*@
7766   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7767 
7768   Collective
7769 
7770   Input Parameters:
7771 + A     - the matrix
7772 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7773 
7774   Output Parameter:
7775 . C - matrix with inverted block diagonal of `A`
7776 
7777   Level: advanced
7778 
7779   Note:
7780   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7781 
7782 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7783 @*/
7784 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7785 {
7786   PetscContainer   container;
7787   EnvelopeData    *edata;
7788   PetscObjectState nonzerostate;
7789 
7790   PetscFunctionBegin;
7791   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7792   if (!container) {
7793     PetscCall(MatComputeVariableBlockEnvelope(A));
7794     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7795   }
7796   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7797   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7798   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7799   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7800 
7801   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7802   *C = edata->C;
7803 
7804   for (PetscInt i = 0; i < edata->n; i++) {
7805     Mat          D;
7806     PetscScalar *dvalues;
7807 
7808     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7809     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7810     PetscCall(MatSeqDenseInvert(D));
7811     PetscCall(MatDenseGetArray(D, &dvalues));
7812     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7813     PetscCall(MatDestroy(&D));
7814   }
7815   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7816   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7817   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7818   PetscFunctionReturn(PETSC_SUCCESS);
7819 }
7820 
7821 /*@
7822   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7823 
7824   Not Collective
7825 
7826   Input Parameters:
7827 + mat     - the matrix
7828 . nblocks - the number of blocks on this process, each block can only exist on a single process
7829 - bsizes  - the block sizes
7830 
7831   Level: intermediate
7832 
7833   Notes:
7834   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7835 
7836   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.
7837 
7838 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7839           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7840 @*/
7841 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7842 {
7843   PetscInt ncnt = 0, nlocal;
7844 
7845   PetscFunctionBegin;
7846   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7847   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7848   PetscCheck(nblocks >= 0 && nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", nblocks, nlocal);
7849   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7850   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);
7851   PetscCall(PetscFree(mat->bsizes));
7852   mat->nblocks = nblocks;
7853   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7854   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7855   PetscFunctionReturn(PETSC_SUCCESS);
7856 }
7857 
7858 /*@C
7859   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7860 
7861   Not Collective; No Fortran Support
7862 
7863   Input Parameter:
7864 . mat - the matrix
7865 
7866   Output Parameters:
7867 + nblocks - the number of blocks on this process
7868 - bsizes  - the block sizes
7869 
7870   Level: intermediate
7871 
7872 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7873 @*/
7874 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7875 {
7876   PetscFunctionBegin;
7877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7878   if (nblocks) *nblocks = mat->nblocks;
7879   if (bsizes) *bsizes = mat->bsizes;
7880   PetscFunctionReturn(PETSC_SUCCESS);
7881 }
7882 
7883 /*@
7884   MatSetBlockSizes - Sets the matrix block row and column sizes.
7885 
7886   Logically Collective
7887 
7888   Input Parameters:
7889 + mat - the matrix
7890 . rbs - row block size
7891 - cbs - column block size
7892 
7893   Level: intermediate
7894 
7895   Notes:
7896   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7897   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7898   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7899 
7900   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7901   are compatible with the matrix local sizes.
7902 
7903   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7904 
7905 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7906 @*/
7907 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7908 {
7909   PetscFunctionBegin;
7910   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7911   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7912   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7913   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7914   if (mat->rmap->refcnt) {
7915     ISLocalToGlobalMapping l2g  = NULL;
7916     PetscLayout            nmap = NULL;
7917 
7918     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7919     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7920     PetscCall(PetscLayoutDestroy(&mat->rmap));
7921     mat->rmap          = nmap;
7922     mat->rmap->mapping = l2g;
7923   }
7924   if (mat->cmap->refcnt) {
7925     ISLocalToGlobalMapping l2g  = NULL;
7926     PetscLayout            nmap = NULL;
7927 
7928     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7929     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7930     PetscCall(PetscLayoutDestroy(&mat->cmap));
7931     mat->cmap          = nmap;
7932     mat->cmap->mapping = l2g;
7933   }
7934   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7935   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7936   PetscFunctionReturn(PETSC_SUCCESS);
7937 }
7938 
7939 /*@
7940   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7941 
7942   Logically Collective
7943 
7944   Input Parameters:
7945 + mat     - the matrix
7946 . fromRow - matrix from which to copy row block size
7947 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7948 
7949   Level: developer
7950 
7951 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7952 @*/
7953 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7954 {
7955   PetscFunctionBegin;
7956   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7957   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7958   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7959   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7960   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7961   PetscFunctionReturn(PETSC_SUCCESS);
7962 }
7963 
7964 /*@
7965   MatResidual - Default routine to calculate the residual r = b - Ax
7966 
7967   Collective
7968 
7969   Input Parameters:
7970 + mat - the matrix
7971 . b   - the right-hand-side
7972 - x   - the approximate solution
7973 
7974   Output Parameter:
7975 . r - location to store the residual
7976 
7977   Level: developer
7978 
7979 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7980 @*/
7981 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7982 {
7983   PetscFunctionBegin;
7984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7985   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7986   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7987   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7988   PetscValidType(mat, 1);
7989   MatCheckPreallocated(mat, 1);
7990   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7991   if (!mat->ops->residual) {
7992     PetscCall(MatMult(mat, x, r));
7993     PetscCall(VecAYPX(r, -1.0, b));
7994   } else {
7995     PetscUseTypeMethod(mat, residual, b, x, r);
7996   }
7997   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7998   PetscFunctionReturn(PETSC_SUCCESS);
7999 }
8000 
8001 /*MC
8002     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8003 
8004     Synopsis:
8005     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8006 
8007     Not Collective
8008 
8009     Input Parameters:
8010 +   A - the matrix
8011 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8012 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8013 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8014                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8015                  always used.
8016 
8017     Output Parameters:
8018 +   n - number of local rows in the (possibly compressed) matrix
8019 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8020 .   ja - the column indices
8021 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8022            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8023 
8024     Level: developer
8025 
8026     Note:
8027     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8028 
8029 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8030 M*/
8031 
8032 /*MC
8033     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8034 
8035     Synopsis:
8036     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8037 
8038     Not Collective
8039 
8040     Input Parameters:
8041 +   A - the  matrix
8042 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8043 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8044     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8045                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8046                  always used.
8047 .   n - number of local rows in the (possibly compressed) matrix
8048 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8049 .   ja - the column indices
8050 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8051            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8052 
8053     Level: developer
8054 
8055 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8056 M*/
8057 
8058 /*@C
8059   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8060 
8061   Collective
8062 
8063   Input Parameters:
8064 + mat             - the matrix
8065 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8066 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8067 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8068                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8069                  always used.
8070 
8071   Output Parameters:
8072 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8073 . 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
8074 . ja   - the column indices, use `NULL` if not needed
8075 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8076            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8077 
8078   Level: developer
8079 
8080   Notes:
8081   You CANNOT change any of the ia[] or ja[] values.
8082 
8083   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8084 
8085   Fortran Notes:
8086   Use
8087 .vb
8088     PetscInt, pointer :: ia(:),ja(:)
8089     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8090     ! Access the ith and jth entries via ia(i) and ja(j)
8091 .ve
8092 
8093   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8094 
8095 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8096 @*/
8097 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8098 {
8099   PetscFunctionBegin;
8100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8101   PetscValidType(mat, 1);
8102   if (n) PetscAssertPointer(n, 5);
8103   if (ia) PetscAssertPointer(ia, 6);
8104   if (ja) PetscAssertPointer(ja, 7);
8105   if (done) PetscAssertPointer(done, 8);
8106   MatCheckPreallocated(mat, 1);
8107   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8108   else {
8109     if (done) *done = PETSC_TRUE;
8110     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8111     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8112     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8113   }
8114   PetscFunctionReturn(PETSC_SUCCESS);
8115 }
8116 
8117 /*@C
8118   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8119 
8120   Collective
8121 
8122   Input Parameters:
8123 + mat             - the matrix
8124 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8125 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8126                 symmetrized
8127 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8128                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8129                  always used.
8130 . n               - number of columns in the (possibly compressed) matrix
8131 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8132 - ja              - the row indices
8133 
8134   Output Parameter:
8135 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8136 
8137   Level: developer
8138 
8139 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8140 @*/
8141 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8142 {
8143   PetscFunctionBegin;
8144   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8145   PetscValidType(mat, 1);
8146   PetscAssertPointer(n, 5);
8147   if (ia) PetscAssertPointer(ia, 6);
8148   if (ja) PetscAssertPointer(ja, 7);
8149   PetscAssertPointer(done, 8);
8150   MatCheckPreallocated(mat, 1);
8151   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8152   else {
8153     *done = PETSC_TRUE;
8154     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8155   }
8156   PetscFunctionReturn(PETSC_SUCCESS);
8157 }
8158 
8159 /*@C
8160   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8161 
8162   Collective
8163 
8164   Input Parameters:
8165 + mat             - the matrix
8166 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8167 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8168 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8169                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8170                  always used.
8171 . n               - size of (possibly compressed) matrix
8172 . ia              - the row pointers
8173 - ja              - the column indices
8174 
8175   Output Parameter:
8176 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8177 
8178   Level: developer
8179 
8180   Note:
8181   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8182   us of the array after it has been restored. If you pass `NULL`, it will
8183   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8184 
8185   Fortran Note:
8186   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8187 
8188 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8189 @*/
8190 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8191 {
8192   PetscFunctionBegin;
8193   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8194   PetscValidType(mat, 1);
8195   if (ia) PetscAssertPointer(ia, 6);
8196   if (ja) PetscAssertPointer(ja, 7);
8197   if (done) PetscAssertPointer(done, 8);
8198   MatCheckPreallocated(mat, 1);
8199 
8200   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8201   else {
8202     if (done) *done = PETSC_TRUE;
8203     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8204     if (n) *n = 0;
8205     if (ia) *ia = NULL;
8206     if (ja) *ja = NULL;
8207   }
8208   PetscFunctionReturn(PETSC_SUCCESS);
8209 }
8210 
8211 /*@C
8212   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8213 
8214   Collective
8215 
8216   Input Parameters:
8217 + mat             - the matrix
8218 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8219 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8220 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8221                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8222                  always used.
8223 
8224   Output Parameters:
8225 + n    - size of (possibly compressed) matrix
8226 . ia   - the column pointers
8227 . ja   - the row indices
8228 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8229 
8230   Level: developer
8231 
8232 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8233 @*/
8234 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8235 {
8236   PetscFunctionBegin;
8237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8238   PetscValidType(mat, 1);
8239   if (ia) PetscAssertPointer(ia, 6);
8240   if (ja) PetscAssertPointer(ja, 7);
8241   PetscAssertPointer(done, 8);
8242   MatCheckPreallocated(mat, 1);
8243 
8244   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8245   else {
8246     *done = PETSC_TRUE;
8247     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8248     if (n) *n = 0;
8249     if (ia) *ia = NULL;
8250     if (ja) *ja = NULL;
8251   }
8252   PetscFunctionReturn(PETSC_SUCCESS);
8253 }
8254 
8255 /*@
8256   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8257   `MatGetColumnIJ()`.
8258 
8259   Collective
8260 
8261   Input Parameters:
8262 + mat        - the matrix
8263 . ncolors    - maximum color value
8264 . n          - number of entries in colorarray
8265 - colorarray - array indicating color for each column
8266 
8267   Output Parameter:
8268 . iscoloring - coloring generated using colorarray information
8269 
8270   Level: developer
8271 
8272 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8273 @*/
8274 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8275 {
8276   PetscFunctionBegin;
8277   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8278   PetscValidType(mat, 1);
8279   PetscAssertPointer(colorarray, 4);
8280   PetscAssertPointer(iscoloring, 5);
8281   MatCheckPreallocated(mat, 1);
8282 
8283   if (!mat->ops->coloringpatch) {
8284     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8285   } else {
8286     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8287   }
8288   PetscFunctionReturn(PETSC_SUCCESS);
8289 }
8290 
8291 /*@
8292   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8293 
8294   Logically Collective
8295 
8296   Input Parameter:
8297 . mat - the factored matrix to be reset
8298 
8299   Level: developer
8300 
8301   Notes:
8302   This routine should be used only with factored matrices formed by in-place
8303   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8304   format).  This option can save memory, for example, when solving nonlinear
8305   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8306   ILU(0) preconditioner.
8307 
8308   One can specify in-place ILU(0) factorization by calling
8309 .vb
8310      PCType(pc,PCILU);
8311      PCFactorSeUseInPlace(pc);
8312 .ve
8313   or by using the options -pc_type ilu -pc_factor_in_place
8314 
8315   In-place factorization ILU(0) can also be used as a local
8316   solver for the blocks within the block Jacobi or additive Schwarz
8317   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8318   for details on setting local solver options.
8319 
8320   Most users should employ the `KSP` interface for linear solvers
8321   instead of working directly with matrix algebra routines such as this.
8322   See, e.g., `KSPCreate()`.
8323 
8324 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8325 @*/
8326 PetscErrorCode MatSetUnfactored(Mat mat)
8327 {
8328   PetscFunctionBegin;
8329   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8330   PetscValidType(mat, 1);
8331   MatCheckPreallocated(mat, 1);
8332   mat->factortype = MAT_FACTOR_NONE;
8333   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8334   PetscUseTypeMethod(mat, setunfactored);
8335   PetscFunctionReturn(PETSC_SUCCESS);
8336 }
8337 
8338 /*MC
8339     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8340 
8341     Synopsis:
8342     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8343 
8344     Not Collective
8345 
8346     Input Parameter:
8347 .   x - matrix
8348 
8349     Output Parameters:
8350 +   xx_v - the Fortran pointer to the array
8351 -   ierr - error code
8352 
8353     Example of Usage:
8354 .vb
8355       PetscScalar, pointer xx_v(:,:)
8356       ....
8357       call MatDenseGetArrayF90(x,xx_v,ierr)
8358       a = xx_v(3)
8359       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8360 .ve
8361 
8362     Level: advanced
8363 
8364 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8365 M*/
8366 
8367 /*MC
8368     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8369     accessed with `MatDenseGetArrayF90()`.
8370 
8371     Synopsis:
8372     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8373 
8374     Not Collective
8375 
8376     Input Parameters:
8377 +   x - matrix
8378 -   xx_v - the Fortran90 pointer to the array
8379 
8380     Output Parameter:
8381 .   ierr - error code
8382 
8383     Example of Usage:
8384 .vb
8385        PetscScalar, pointer xx_v(:,:)
8386        ....
8387        call MatDenseGetArrayF90(x,xx_v,ierr)
8388        a = xx_v(3)
8389        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8390 .ve
8391 
8392     Level: advanced
8393 
8394 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8395 M*/
8396 
8397 /*MC
8398     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8399 
8400     Synopsis:
8401     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8402 
8403     Not Collective
8404 
8405     Input Parameter:
8406 .   x - matrix
8407 
8408     Output Parameters:
8409 +   xx_v - the Fortran pointer to the array
8410 -   ierr - error code
8411 
8412     Example of Usage:
8413 .vb
8414       PetscScalar, pointer xx_v(:)
8415       ....
8416       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8417       a = xx_v(3)
8418       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8419 .ve
8420 
8421     Level: advanced
8422 
8423 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8424 M*/
8425 
8426 /*MC
8427     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8428     accessed with `MatSeqAIJGetArrayF90()`.
8429 
8430     Synopsis:
8431     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8432 
8433     Not Collective
8434 
8435     Input Parameters:
8436 +   x - matrix
8437 -   xx_v - the Fortran90 pointer to the array
8438 
8439     Output Parameter:
8440 .   ierr - error code
8441 
8442     Example of Usage:
8443 .vb
8444        PetscScalar, pointer xx_v(:)
8445        ....
8446        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8447        a = xx_v(3)
8448        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8449 .ve
8450 
8451     Level: advanced
8452 
8453 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8454 M*/
8455 
8456 /*@
8457   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8458   as the original matrix.
8459 
8460   Collective
8461 
8462   Input Parameters:
8463 + mat   - the original matrix
8464 . isrow - parallel `IS` containing the rows this processor should obtain
8465 . 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.
8466 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8467 
8468   Output Parameter:
8469 . newmat - the new submatrix, of the same type as the original matrix
8470 
8471   Level: advanced
8472 
8473   Notes:
8474   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8475 
8476   Some matrix types place restrictions on the row and column indices, such
8477   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;
8478   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8479 
8480   The index sets may not have duplicate entries.
8481 
8482   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8483   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8484   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8485   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8486   you are finished using it.
8487 
8488   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8489   the input matrix.
8490 
8491   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8492 
8493   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8494   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8495 
8496   Example usage:
8497   Consider the following 8x8 matrix with 34 non-zero values, that is
8498   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8499   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8500   as follows
8501 .vb
8502             1  2  0  |  0  3  0  |  0  4
8503     Proc0   0  5  6  |  7  0  0  |  8  0
8504             9  0 10  | 11  0  0  | 12  0
8505     -------------------------------------
8506            13  0 14  | 15 16 17  |  0  0
8507     Proc1   0 18  0  | 19 20 21  |  0  0
8508             0  0  0  | 22 23  0  | 24  0
8509     -------------------------------------
8510     Proc2  25 26 27  |  0  0 28  | 29  0
8511            30  0  0  | 31 32 33  |  0 34
8512 .ve
8513 
8514   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8515 
8516 .vb
8517             2  0  |  0  3  0  |  0
8518     Proc0   5  6  |  7  0  0  |  8
8519     -------------------------------
8520     Proc1  18  0  | 19 20 21  |  0
8521     -------------------------------
8522     Proc2  26 27  |  0  0 28  | 29
8523             0  0  | 31 32 33  |  0
8524 .ve
8525 
8526 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8527 @*/
8528 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8529 {
8530   PetscMPIInt size;
8531   Mat        *local;
8532   IS          iscoltmp;
8533   PetscBool   flg;
8534 
8535   PetscFunctionBegin;
8536   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8537   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8538   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8539   PetscAssertPointer(newmat, 5);
8540   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8541   PetscValidType(mat, 1);
8542   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8543   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8544 
8545   MatCheckPreallocated(mat, 1);
8546   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8547 
8548   if (!iscol || isrow == iscol) {
8549     PetscBool   stride;
8550     PetscMPIInt grabentirematrix = 0, grab;
8551     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8552     if (stride) {
8553       PetscInt first, step, n, rstart, rend;
8554       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8555       if (step == 1) {
8556         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8557         if (rstart == first) {
8558           PetscCall(ISGetLocalSize(isrow, &n));
8559           if (n == rend - rstart) grabentirematrix = 1;
8560         }
8561       }
8562     }
8563     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8564     if (grab) {
8565       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8566       if (cll == MAT_INITIAL_MATRIX) {
8567         *newmat = mat;
8568         PetscCall(PetscObjectReference((PetscObject)mat));
8569       }
8570       PetscFunctionReturn(PETSC_SUCCESS);
8571     }
8572   }
8573 
8574   if (!iscol) {
8575     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8576   } else {
8577     iscoltmp = iscol;
8578   }
8579 
8580   /* if original matrix is on just one processor then use submatrix generated */
8581   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8582     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8583     goto setproperties;
8584   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8585     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8586     *newmat = *local;
8587     PetscCall(PetscFree(local));
8588     goto setproperties;
8589   } else if (!mat->ops->createsubmatrix) {
8590     /* Create a new matrix type that implements the operation using the full matrix */
8591     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8592     switch (cll) {
8593     case MAT_INITIAL_MATRIX:
8594       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8595       break;
8596     case MAT_REUSE_MATRIX:
8597       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8598       break;
8599     default:
8600       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8601     }
8602     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8603     goto setproperties;
8604   }
8605 
8606   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8607   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8608   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8609 
8610 setproperties:
8611   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8612   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8613   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8614   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8615   PetscFunctionReturn(PETSC_SUCCESS);
8616 }
8617 
8618 /*@
8619   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8620 
8621   Not Collective
8622 
8623   Input Parameters:
8624 + A - the matrix we wish to propagate options from
8625 - B - the matrix we wish to propagate options to
8626 
8627   Level: beginner
8628 
8629   Note:
8630   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8631 
8632 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8633 @*/
8634 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8635 {
8636   PetscFunctionBegin;
8637   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8638   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8639   B->symmetry_eternal            = A->symmetry_eternal;
8640   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8641   B->symmetric                   = A->symmetric;
8642   B->structurally_symmetric      = A->structurally_symmetric;
8643   B->spd                         = A->spd;
8644   B->hermitian                   = A->hermitian;
8645   PetscFunctionReturn(PETSC_SUCCESS);
8646 }
8647 
8648 /*@
8649   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8650   used during the assembly process to store values that belong to
8651   other processors.
8652 
8653   Not Collective
8654 
8655   Input Parameters:
8656 + mat   - the matrix
8657 . size  - the initial size of the stash.
8658 - bsize - the initial size of the block-stash(if used).
8659 
8660   Options Database Keys:
8661 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8662 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8663 
8664   Level: intermediate
8665 
8666   Notes:
8667   The block-stash is used for values set with `MatSetValuesBlocked()` while
8668   the stash is used for values set with `MatSetValues()`
8669 
8670   Run with the option -info and look for output of the form
8671   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8672   to determine the appropriate value, MM, to use for size and
8673   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8674   to determine the value, BMM to use for bsize
8675 
8676 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8677 @*/
8678 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8679 {
8680   PetscFunctionBegin;
8681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8682   PetscValidType(mat, 1);
8683   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8684   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8685   PetscFunctionReturn(PETSC_SUCCESS);
8686 }
8687 
8688 /*@
8689   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8690   the matrix
8691 
8692   Neighbor-wise Collective
8693 
8694   Input Parameters:
8695 + A - the matrix
8696 . x - the vector to be multiplied by the interpolation operator
8697 - y - the vector to be added to the result
8698 
8699   Output Parameter:
8700 . w - the resulting vector
8701 
8702   Level: intermediate
8703 
8704   Notes:
8705   `w` may be the same vector as `y`.
8706 
8707   This allows one to use either the restriction or interpolation (its transpose)
8708   matrix to do the interpolation
8709 
8710 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8711 @*/
8712 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8713 {
8714   PetscInt M, N, Ny;
8715 
8716   PetscFunctionBegin;
8717   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8718   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8719   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8720   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8721   PetscCall(MatGetSize(A, &M, &N));
8722   PetscCall(VecGetSize(y, &Ny));
8723   if (M == Ny) {
8724     PetscCall(MatMultAdd(A, x, y, w));
8725   } else {
8726     PetscCall(MatMultTransposeAdd(A, x, y, w));
8727   }
8728   PetscFunctionReturn(PETSC_SUCCESS);
8729 }
8730 
8731 /*@
8732   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8733   the matrix
8734 
8735   Neighbor-wise Collective
8736 
8737   Input Parameters:
8738 + A - the matrix
8739 - x - the vector to be interpolated
8740 
8741   Output Parameter:
8742 . y - the resulting vector
8743 
8744   Level: intermediate
8745 
8746   Note:
8747   This allows one to use either the restriction or interpolation (its transpose)
8748   matrix to do the interpolation
8749 
8750 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8751 @*/
8752 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8753 {
8754   PetscInt M, N, Ny;
8755 
8756   PetscFunctionBegin;
8757   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8758   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8759   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8760   PetscCall(MatGetSize(A, &M, &N));
8761   PetscCall(VecGetSize(y, &Ny));
8762   if (M == Ny) {
8763     PetscCall(MatMult(A, x, y));
8764   } else {
8765     PetscCall(MatMultTranspose(A, x, y));
8766   }
8767   PetscFunctionReturn(PETSC_SUCCESS);
8768 }
8769 
8770 /*@
8771   MatRestrict - $y = A*x$ or $A^T*x$
8772 
8773   Neighbor-wise Collective
8774 
8775   Input Parameters:
8776 + A - the matrix
8777 - x - the vector to be restricted
8778 
8779   Output Parameter:
8780 . y - the resulting vector
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 restriction
8787 
8788 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8789 @*/
8790 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8791 {
8792   PetscInt M, N, Nx;
8793 
8794   PetscFunctionBegin;
8795   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8796   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8797   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8798   PetscCall(MatGetSize(A, &M, &N));
8799   PetscCall(VecGetSize(x, &Nx));
8800   if (M == Nx) {
8801     PetscCall(MatMultTranspose(A, x, y));
8802   } else {
8803     PetscCall(MatMult(A, x, y));
8804   }
8805   PetscFunctionReturn(PETSC_SUCCESS);
8806 }
8807 
8808 /*@
8809   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8810 
8811   Neighbor-wise Collective
8812 
8813   Input Parameters:
8814 + A - the matrix
8815 . x - the input dense matrix to be multiplied
8816 - w - the input dense matrix to be added to the result
8817 
8818   Output Parameter:
8819 . y - the output dense matrix
8820 
8821   Level: intermediate
8822 
8823   Note:
8824   This allows one to use either the restriction or interpolation (its transpose)
8825   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8826   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8827 
8828 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8829 @*/
8830 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8831 {
8832   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8833   PetscBool trans = PETSC_TRUE;
8834   MatReuse  reuse = MAT_INITIAL_MATRIX;
8835 
8836   PetscFunctionBegin;
8837   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8838   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8839   PetscValidType(x, 2);
8840   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8841   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8842   PetscCall(MatGetSize(A, &M, &N));
8843   PetscCall(MatGetSize(x, &Mx, &Nx));
8844   if (N == Mx) trans = PETSC_FALSE;
8845   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);
8846   Mo = trans ? N : M;
8847   if (*y) {
8848     PetscCall(MatGetSize(*y, &My, &Ny));
8849     if (Mo == My && Nx == Ny) {
8850       reuse = MAT_REUSE_MATRIX;
8851     } else {
8852       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);
8853       PetscCall(MatDestroy(y));
8854     }
8855   }
8856 
8857   if (w && *y == w) { /* this is to minimize changes in PCMG */
8858     PetscBool flg;
8859 
8860     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8861     if (w) {
8862       PetscInt My, Ny, Mw, Nw;
8863 
8864       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8865       PetscCall(MatGetSize(*y, &My, &Ny));
8866       PetscCall(MatGetSize(w, &Mw, &Nw));
8867       if (!flg || My != Mw || Ny != Nw) w = NULL;
8868     }
8869     if (!w) {
8870       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8871       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8872       PetscCall(PetscObjectDereference((PetscObject)w));
8873     } else {
8874       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8875     }
8876   }
8877   if (!trans) {
8878     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8879   } else {
8880     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8881   }
8882   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8883   PetscFunctionReturn(PETSC_SUCCESS);
8884 }
8885 
8886 /*@
8887   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8888 
8889   Neighbor-wise Collective
8890 
8891   Input Parameters:
8892 + A - the matrix
8893 - x - the input dense matrix
8894 
8895   Output Parameter:
8896 . y - the output dense matrix
8897 
8898   Level: intermediate
8899 
8900   Note:
8901   This allows one to use either the restriction or interpolation (its transpose)
8902   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8903   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8904 
8905 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8906 @*/
8907 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8908 {
8909   PetscFunctionBegin;
8910   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8911   PetscFunctionReturn(PETSC_SUCCESS);
8912 }
8913 
8914 /*@
8915   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8916 
8917   Neighbor-wise Collective
8918 
8919   Input Parameters:
8920 + A - the matrix
8921 - x - the input dense matrix
8922 
8923   Output Parameter:
8924 . y - the output dense matrix
8925 
8926   Level: intermediate
8927 
8928   Note:
8929   This allows one to use either the restriction or interpolation (its transpose)
8930   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8931   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8932 
8933 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8934 @*/
8935 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8936 {
8937   PetscFunctionBegin;
8938   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8939   PetscFunctionReturn(PETSC_SUCCESS);
8940 }
8941 
8942 /*@
8943   MatGetNullSpace - retrieves the null space of a matrix.
8944 
8945   Logically Collective
8946 
8947   Input Parameters:
8948 + mat    - the matrix
8949 - nullsp - the null space object
8950 
8951   Level: developer
8952 
8953 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8954 @*/
8955 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8956 {
8957   PetscFunctionBegin;
8958   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8959   PetscAssertPointer(nullsp, 2);
8960   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8961   PetscFunctionReturn(PETSC_SUCCESS);
8962 }
8963 
8964 /*@C
8965   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8966 
8967   Logically Collective
8968 
8969   Input Parameters:
8970 + n   - the number of matrices
8971 - mat - the array of matrices
8972 
8973   Output Parameters:
8974 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space
8975 
8976   Level: developer
8977 
8978   Note:
8979   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8980 
8981 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8982           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8983 @*/
8984 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8985 {
8986   PetscFunctionBegin;
8987   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8988   PetscAssertPointer(mat, 2);
8989   PetscAssertPointer(nullsp, 3);
8990 
8991   PetscCall(PetscCalloc1(3 * n, nullsp));
8992   for (PetscInt i = 0; i < n; i++) {
8993     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8994     (*nullsp)[i] = mat[i]->nullsp;
8995     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8996     (*nullsp)[n + i] = mat[i]->nearnullsp;
8997     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8998     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8999     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9000   }
9001   PetscFunctionReturn(PETSC_SUCCESS);
9002 }
9003 
9004 /*@C
9005   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9006 
9007   Logically Collective
9008 
9009   Input Parameters:
9010 + n      - the number of matrices
9011 . mat    - the array of matrices
9012 - nullsp - an array of null spaces, `NULL` if the null space does not exist
9013 
9014   Level: developer
9015 
9016   Note:
9017   Call `MatGetNullSpaces()` to create `nullsp`
9018 
9019 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9020           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9021 @*/
9022 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9023 {
9024   PetscFunctionBegin;
9025   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9026   PetscAssertPointer(mat, 2);
9027   PetscAssertPointer(nullsp, 3);
9028   PetscAssertPointer(*nullsp, 3);
9029 
9030   for (PetscInt i = 0; i < n; i++) {
9031     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9032     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9033     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9034     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9035     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9036     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9037     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9038   }
9039   PetscCall(PetscFree(*nullsp));
9040   PetscFunctionReturn(PETSC_SUCCESS);
9041 }
9042 
9043 /*@
9044   MatSetNullSpace - attaches a null space to a matrix.
9045 
9046   Logically Collective
9047 
9048   Input Parameters:
9049 + mat    - the matrix
9050 - nullsp - the null space object
9051 
9052   Level: advanced
9053 
9054   Notes:
9055   This null space is used by the `KSP` linear solvers to solve singular systems.
9056 
9057   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`
9058 
9059   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
9060   to zero but the linear system will still be solved in a least squares sense.
9061 
9062   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9063   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)$.
9064   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
9065   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
9066   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$).
9067   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9068 
9069   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9070   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9071   routine also automatically calls `MatSetTransposeNullSpace()`.
9072 
9073   The user should call `MatNullSpaceDestroy()`.
9074 
9075 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9076           `KSPSetPCSide()`
9077 @*/
9078 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9079 {
9080   PetscFunctionBegin;
9081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9082   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9083   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9084   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9085   mat->nullsp = nullsp;
9086   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9087   PetscFunctionReturn(PETSC_SUCCESS);
9088 }
9089 
9090 /*@
9091   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9092 
9093   Logically Collective
9094 
9095   Input Parameters:
9096 + mat    - the matrix
9097 - nullsp - the null space object
9098 
9099   Level: developer
9100 
9101 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9102 @*/
9103 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9104 {
9105   PetscFunctionBegin;
9106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9107   PetscValidType(mat, 1);
9108   PetscAssertPointer(nullsp, 2);
9109   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9110   PetscFunctionReturn(PETSC_SUCCESS);
9111 }
9112 
9113 /*@
9114   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9115 
9116   Logically Collective
9117 
9118   Input Parameters:
9119 + mat    - the matrix
9120 - nullsp - the null space object
9121 
9122   Level: advanced
9123 
9124   Notes:
9125   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9126 
9127   See `MatSetNullSpace()`
9128 
9129 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9130 @*/
9131 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9132 {
9133   PetscFunctionBegin;
9134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9135   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9136   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9137   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9138   mat->transnullsp = nullsp;
9139   PetscFunctionReturn(PETSC_SUCCESS);
9140 }
9141 
9142 /*@
9143   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9144   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9145 
9146   Logically Collective
9147 
9148   Input Parameters:
9149 + mat    - the matrix
9150 - nullsp - the null space object
9151 
9152   Level: advanced
9153 
9154   Notes:
9155   Overwrites any previous near null space that may have been attached
9156 
9157   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9158 
9159 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9160 @*/
9161 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9162 {
9163   PetscFunctionBegin;
9164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9165   PetscValidType(mat, 1);
9166   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9167   MatCheckPreallocated(mat, 1);
9168   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9169   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9170   mat->nearnullsp = nullsp;
9171   PetscFunctionReturn(PETSC_SUCCESS);
9172 }
9173 
9174 /*@
9175   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9176 
9177   Not Collective
9178 
9179   Input Parameter:
9180 . mat - the matrix
9181 
9182   Output Parameter:
9183 . nullsp - the null space object, `NULL` if not set
9184 
9185   Level: advanced
9186 
9187 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9188 @*/
9189 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9190 {
9191   PetscFunctionBegin;
9192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9193   PetscValidType(mat, 1);
9194   PetscAssertPointer(nullsp, 2);
9195   MatCheckPreallocated(mat, 1);
9196   *nullsp = mat->nearnullsp;
9197   PetscFunctionReturn(PETSC_SUCCESS);
9198 }
9199 
9200 /*@C
9201   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9202 
9203   Collective
9204 
9205   Input Parameters:
9206 + mat  - the matrix
9207 . row  - row/column permutation
9208 - info - information on desired factorization process
9209 
9210   Level: developer
9211 
9212   Notes:
9213   Probably really in-place only when level of fill is zero, otherwise allocates
9214   new space to store factored matrix and deletes previous memory.
9215 
9216   Most users should employ the `KSP` interface for linear solvers
9217   instead of working directly with matrix algebra routines such as this.
9218   See, e.g., `KSPCreate()`.
9219 
9220   Developer Note:
9221   The Fortran interface is not autogenerated as the
9222   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9223 
9224 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9225 @*/
9226 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9227 {
9228   PetscFunctionBegin;
9229   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9230   PetscValidType(mat, 1);
9231   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9232   PetscAssertPointer(info, 3);
9233   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9234   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9235   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9236   MatCheckPreallocated(mat, 1);
9237   PetscUseTypeMethod(mat, iccfactor, row, info);
9238   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9239   PetscFunctionReturn(PETSC_SUCCESS);
9240 }
9241 
9242 /*@
9243   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9244   ghosted ones.
9245 
9246   Not Collective
9247 
9248   Input Parameters:
9249 + mat  - the matrix
9250 - diag - the diagonal values, including ghost ones
9251 
9252   Level: developer
9253 
9254   Notes:
9255   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9256 
9257   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9258 
9259 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9260 @*/
9261 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9262 {
9263   PetscMPIInt size;
9264 
9265   PetscFunctionBegin;
9266   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9267   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9268   PetscValidType(mat, 1);
9269 
9270   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9271   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9272   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9273   if (size == 1) {
9274     PetscInt n, m;
9275     PetscCall(VecGetSize(diag, &n));
9276     PetscCall(MatGetSize(mat, NULL, &m));
9277     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9278     PetscCall(MatDiagonalScale(mat, NULL, diag));
9279   } else {
9280     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9281   }
9282   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9283   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9284   PetscFunctionReturn(PETSC_SUCCESS);
9285 }
9286 
9287 /*@
9288   MatGetInertia - Gets the inertia from a factored matrix
9289 
9290   Collective
9291 
9292   Input Parameter:
9293 . mat - the matrix
9294 
9295   Output Parameters:
9296 + nneg  - number of negative eigenvalues
9297 . nzero - number of zero eigenvalues
9298 - npos  - number of positive eigenvalues
9299 
9300   Level: advanced
9301 
9302   Note:
9303   Matrix must have been factored by `MatCholeskyFactor()`
9304 
9305 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9306 @*/
9307 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9308 {
9309   PetscFunctionBegin;
9310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9311   PetscValidType(mat, 1);
9312   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9313   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9314   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9315   PetscFunctionReturn(PETSC_SUCCESS);
9316 }
9317 
9318 /*@C
9319   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9320 
9321   Neighbor-wise Collective
9322 
9323   Input Parameters:
9324 + mat - the factored matrix obtained with `MatGetFactor()`
9325 - b   - the right-hand-side vectors
9326 
9327   Output Parameter:
9328 . x - the result vectors
9329 
9330   Level: developer
9331 
9332   Note:
9333   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9334   call `MatSolves`(A,x,x).
9335 
9336 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9337 @*/
9338 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9339 {
9340   PetscFunctionBegin;
9341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9342   PetscValidType(mat, 1);
9343   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9344   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9345   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9346 
9347   MatCheckPreallocated(mat, 1);
9348   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9349   PetscUseTypeMethod(mat, solves, b, x);
9350   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9351   PetscFunctionReturn(PETSC_SUCCESS);
9352 }
9353 
9354 /*@
9355   MatIsSymmetric - Test whether a matrix is symmetric
9356 
9357   Collective
9358 
9359   Input Parameters:
9360 + A   - the matrix to test
9361 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9362 
9363   Output Parameter:
9364 . flg - the result
9365 
9366   Level: intermediate
9367 
9368   Notes:
9369   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9370 
9371   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9372 
9373   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9374   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9375 
9376 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9377           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9378 @*/
9379 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9380 {
9381   PetscFunctionBegin;
9382   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9383   PetscAssertPointer(flg, 3);
9384   if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric);
9385   else {
9386     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9387     else PetscCall(MatIsTranspose(A, A, tol, flg));
9388     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9389   }
9390   PetscFunctionReturn(PETSC_SUCCESS);
9391 }
9392 
9393 /*@
9394   MatIsHermitian - Test whether a matrix is Hermitian
9395 
9396   Collective
9397 
9398   Input Parameters:
9399 + A   - the matrix to test
9400 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9401 
9402   Output Parameter:
9403 . flg - the result
9404 
9405   Level: intermediate
9406 
9407   Notes:
9408   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9409 
9410   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9411 
9412   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9413   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9414 
9415 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9416           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9417 @*/
9418 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9419 {
9420   PetscFunctionBegin;
9421   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9422   PetscAssertPointer(flg, 3);
9423   if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian);
9424   else {
9425     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9426     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9427     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9428   }
9429   PetscFunctionReturn(PETSC_SUCCESS);
9430 }
9431 
9432 /*@
9433   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9434 
9435   Not Collective
9436 
9437   Input Parameter:
9438 . A - the matrix to check
9439 
9440   Output Parameters:
9441 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9442 - flg - the result (only valid if set is `PETSC_TRUE`)
9443 
9444   Level: advanced
9445 
9446   Notes:
9447   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9448   if you want it explicitly checked
9449 
9450   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9451   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9452 
9453 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9454 @*/
9455 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9456 {
9457   PetscFunctionBegin;
9458   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9459   PetscAssertPointer(set, 2);
9460   PetscAssertPointer(flg, 3);
9461   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9462     *set = PETSC_TRUE;
9463     *flg = PetscBool3ToBool(A->symmetric);
9464   } else {
9465     *set = PETSC_FALSE;
9466   }
9467   PetscFunctionReturn(PETSC_SUCCESS);
9468 }
9469 
9470 /*@
9471   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9472 
9473   Not Collective
9474 
9475   Input Parameter:
9476 . A - the matrix to check
9477 
9478   Output Parameters:
9479 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9480 - flg - the result (only valid if set is `PETSC_TRUE`)
9481 
9482   Level: advanced
9483 
9484   Notes:
9485   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9486 
9487   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9488   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9489 
9490 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9491 @*/
9492 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9493 {
9494   PetscFunctionBegin;
9495   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9496   PetscAssertPointer(set, 2);
9497   PetscAssertPointer(flg, 3);
9498   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9499     *set = PETSC_TRUE;
9500     *flg = PetscBool3ToBool(A->spd);
9501   } else {
9502     *set = PETSC_FALSE;
9503   }
9504   PetscFunctionReturn(PETSC_SUCCESS);
9505 }
9506 
9507 /*@
9508   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9509 
9510   Not Collective
9511 
9512   Input Parameter:
9513 . A - the matrix to check
9514 
9515   Output Parameters:
9516 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9517 - flg - the result (only valid if set is `PETSC_TRUE`)
9518 
9519   Level: advanced
9520 
9521   Notes:
9522   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9523   if you want it explicitly checked
9524 
9525   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9526   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9527 
9528 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9529 @*/
9530 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9531 {
9532   PetscFunctionBegin;
9533   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9534   PetscAssertPointer(set, 2);
9535   PetscAssertPointer(flg, 3);
9536   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9537     *set = PETSC_TRUE;
9538     *flg = PetscBool3ToBool(A->hermitian);
9539   } else {
9540     *set = PETSC_FALSE;
9541   }
9542   PetscFunctionReturn(PETSC_SUCCESS);
9543 }
9544 
9545 /*@
9546   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9547 
9548   Collective
9549 
9550   Input Parameter:
9551 . A - the matrix to test
9552 
9553   Output Parameter:
9554 . flg - the result
9555 
9556   Level: intermediate
9557 
9558   Notes:
9559   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9560 
9561   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
9562   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9563 
9564 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9565 @*/
9566 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9567 {
9568   PetscFunctionBegin;
9569   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9570   PetscAssertPointer(flg, 2);
9571   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9572     *flg = PetscBool3ToBool(A->structurally_symmetric);
9573   } else {
9574     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9575     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9576   }
9577   PetscFunctionReturn(PETSC_SUCCESS);
9578 }
9579 
9580 /*@
9581   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9582 
9583   Not Collective
9584 
9585   Input Parameter:
9586 . A - the matrix to check
9587 
9588   Output Parameters:
9589 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9590 - flg - the result (only valid if set is PETSC_TRUE)
9591 
9592   Level: advanced
9593 
9594   Notes:
9595   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
9596   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9597 
9598   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9599 
9600 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9601 @*/
9602 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9603 {
9604   PetscFunctionBegin;
9605   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9606   PetscAssertPointer(set, 2);
9607   PetscAssertPointer(flg, 3);
9608   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9609     *set = PETSC_TRUE;
9610     *flg = PetscBool3ToBool(A->structurally_symmetric);
9611   } else {
9612     *set = PETSC_FALSE;
9613   }
9614   PetscFunctionReturn(PETSC_SUCCESS);
9615 }
9616 
9617 /*@
9618   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9619   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9620 
9621   Not Collective
9622 
9623   Input Parameter:
9624 . mat - the matrix
9625 
9626   Output Parameters:
9627 + nstash    - the size of the stash
9628 . reallocs  - the number of additional mallocs incurred.
9629 . bnstash   - the size of the block stash
9630 - breallocs - the number of additional mallocs incurred.in the block stash
9631 
9632   Level: advanced
9633 
9634 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9635 @*/
9636 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9637 {
9638   PetscFunctionBegin;
9639   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9640   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9641   PetscFunctionReturn(PETSC_SUCCESS);
9642 }
9643 
9644 /*@C
9645   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9646   parallel layout, `PetscLayout` for rows and columns
9647 
9648   Collective
9649 
9650   Input Parameter:
9651 . mat - the matrix
9652 
9653   Output Parameters:
9654 + right - (optional) vector that the matrix can be multiplied against
9655 - left  - (optional) vector that the matrix vector product can be stored in
9656 
9657   Level: advanced
9658 
9659   Notes:
9660   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()`.
9661 
9662   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9663 
9664 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9665 @*/
9666 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9667 {
9668   PetscFunctionBegin;
9669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9670   PetscValidType(mat, 1);
9671   if (mat->ops->getvecs) {
9672     PetscUseTypeMethod(mat, getvecs, right, left);
9673   } else {
9674     if (right) {
9675       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9676       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9677       PetscCall(VecSetType(*right, mat->defaultvectype));
9678 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9679       if (mat->boundtocpu && mat->bindingpropagates) {
9680         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9681         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9682       }
9683 #endif
9684     }
9685     if (left) {
9686       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9687       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9688       PetscCall(VecSetType(*left, mat->defaultvectype));
9689 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9690       if (mat->boundtocpu && mat->bindingpropagates) {
9691         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9692         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9693       }
9694 #endif
9695     }
9696   }
9697   PetscFunctionReturn(PETSC_SUCCESS);
9698 }
9699 
9700 /*@C
9701   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9702   with default values.
9703 
9704   Not Collective
9705 
9706   Input Parameter:
9707 . info - the `MatFactorInfo` data structure
9708 
9709   Level: developer
9710 
9711   Notes:
9712   The solvers are generally used through the `KSP` and `PC` objects, for example
9713   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9714 
9715   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9716 
9717   Developer Note:
9718   The Fortran interface is not autogenerated as the
9719   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9720 
9721 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9722 @*/
9723 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9724 {
9725   PetscFunctionBegin;
9726   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9727   PetscFunctionReturn(PETSC_SUCCESS);
9728 }
9729 
9730 /*@
9731   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9732 
9733   Collective
9734 
9735   Input Parameters:
9736 + mat - the factored matrix
9737 - is  - the index set defining the Schur indices (0-based)
9738 
9739   Level: advanced
9740 
9741   Notes:
9742   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9743 
9744   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9745 
9746   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9747 
9748 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9749           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9750 @*/
9751 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9752 {
9753   PetscErrorCode (*f)(Mat, IS);
9754 
9755   PetscFunctionBegin;
9756   PetscValidType(mat, 1);
9757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9758   PetscValidType(is, 2);
9759   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9760   PetscCheckSameComm(mat, 1, is, 2);
9761   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9762   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9763   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9764   PetscCall(MatDestroy(&mat->schur));
9765   PetscCall((*f)(mat, is));
9766   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9767   PetscFunctionReturn(PETSC_SUCCESS);
9768 }
9769 
9770 /*@
9771   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9772 
9773   Logically Collective
9774 
9775   Input Parameters:
9776 + F      - the factored matrix obtained by calling `MatGetFactor()`
9777 . S      - location where to return the Schur complement, can be `NULL`
9778 - status - the status of the Schur complement matrix, can be `NULL`
9779 
9780   Level: advanced
9781 
9782   Notes:
9783   You must call `MatFactorSetSchurIS()` before calling this routine.
9784 
9785   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9786 
9787   The routine provides a copy of the Schur matrix stored within the solver data structures.
9788   The caller must destroy the object when it is no longer needed.
9789   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9790 
9791   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)
9792 
9793   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9794 
9795   Developer Note:
9796   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9797   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9798 
9799 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9800 @*/
9801 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9802 {
9803   PetscFunctionBegin;
9804   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9805   if (S) PetscAssertPointer(S, 2);
9806   if (status) PetscAssertPointer(status, 3);
9807   if (S) {
9808     PetscErrorCode (*f)(Mat, Mat *);
9809 
9810     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9811     if (f) {
9812       PetscCall((*f)(F, S));
9813     } else {
9814       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9815     }
9816   }
9817   if (status) *status = F->schur_status;
9818   PetscFunctionReturn(PETSC_SUCCESS);
9819 }
9820 
9821 /*@
9822   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9823 
9824   Logically Collective
9825 
9826   Input Parameters:
9827 + F      - the factored matrix obtained by calling `MatGetFactor()`
9828 . S      - location where to return the Schur complement, can be `NULL`
9829 - status - the status of the Schur complement matrix, can be `NULL`
9830 
9831   Level: advanced
9832 
9833   Notes:
9834   You must call `MatFactorSetSchurIS()` before calling this routine.
9835 
9836   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9837 
9838   The routine returns a the Schur Complement stored within the data structures of the solver.
9839 
9840   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9841 
9842   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9843 
9844   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9845 
9846   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9847 
9848 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9849 @*/
9850 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9851 {
9852   PetscFunctionBegin;
9853   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9854   if (S) {
9855     PetscAssertPointer(S, 2);
9856     *S = F->schur;
9857   }
9858   if (status) {
9859     PetscAssertPointer(status, 3);
9860     *status = F->schur_status;
9861   }
9862   PetscFunctionReturn(PETSC_SUCCESS);
9863 }
9864 
9865 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9866 {
9867   Mat S = F->schur;
9868 
9869   PetscFunctionBegin;
9870   switch (F->schur_status) {
9871   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9872   case MAT_FACTOR_SCHUR_INVERTED:
9873     if (S) {
9874       S->ops->solve             = NULL;
9875       S->ops->matsolve          = NULL;
9876       S->ops->solvetranspose    = NULL;
9877       S->ops->matsolvetranspose = NULL;
9878       S->ops->solveadd          = NULL;
9879       S->ops->solvetransposeadd = NULL;
9880       S->factortype             = MAT_FACTOR_NONE;
9881       PetscCall(PetscFree(S->solvertype));
9882     }
9883   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9884     break;
9885   default:
9886     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9887   }
9888   PetscFunctionReturn(PETSC_SUCCESS);
9889 }
9890 
9891 /*@
9892   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9893 
9894   Logically Collective
9895 
9896   Input Parameters:
9897 + F      - the factored matrix obtained by calling `MatGetFactor()`
9898 . S      - location where the Schur complement is stored
9899 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9900 
9901   Level: advanced
9902 
9903 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9904 @*/
9905 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9906 {
9907   PetscFunctionBegin;
9908   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9909   if (S) {
9910     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9911     *S = NULL;
9912   }
9913   F->schur_status = status;
9914   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9915   PetscFunctionReturn(PETSC_SUCCESS);
9916 }
9917 
9918 /*@
9919   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9920 
9921   Logically Collective
9922 
9923   Input Parameters:
9924 + F   - the factored matrix obtained by calling `MatGetFactor()`
9925 . rhs - location where the right-hand side of the Schur complement system is stored
9926 - sol - location where the solution of the Schur complement system has to be returned
9927 
9928   Level: advanced
9929 
9930   Notes:
9931   The sizes of the vectors should match the size of the Schur complement
9932 
9933   Must be called after `MatFactorSetSchurIS()`
9934 
9935 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9936 @*/
9937 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9938 {
9939   PetscFunctionBegin;
9940   PetscValidType(F, 1);
9941   PetscValidType(rhs, 2);
9942   PetscValidType(sol, 3);
9943   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9944   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9945   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9946   PetscCheckSameComm(F, 1, rhs, 2);
9947   PetscCheckSameComm(F, 1, sol, 3);
9948   PetscCall(MatFactorFactorizeSchurComplement(F));
9949   switch (F->schur_status) {
9950   case MAT_FACTOR_SCHUR_FACTORED:
9951     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9952     break;
9953   case MAT_FACTOR_SCHUR_INVERTED:
9954     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9955     break;
9956   default:
9957     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9958   }
9959   PetscFunctionReturn(PETSC_SUCCESS);
9960 }
9961 
9962 /*@
9963   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9964 
9965   Logically Collective
9966 
9967   Input Parameters:
9968 + F   - the factored matrix obtained by calling `MatGetFactor()`
9969 . rhs - location where the right-hand side of the Schur complement system is stored
9970 - sol - location where the solution of the Schur complement system has to be returned
9971 
9972   Level: advanced
9973 
9974   Notes:
9975   The sizes of the vectors should match the size of the Schur complement
9976 
9977   Must be called after `MatFactorSetSchurIS()`
9978 
9979 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9980 @*/
9981 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9982 {
9983   PetscFunctionBegin;
9984   PetscValidType(F, 1);
9985   PetscValidType(rhs, 2);
9986   PetscValidType(sol, 3);
9987   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9988   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9989   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9990   PetscCheckSameComm(F, 1, rhs, 2);
9991   PetscCheckSameComm(F, 1, sol, 3);
9992   PetscCall(MatFactorFactorizeSchurComplement(F));
9993   switch (F->schur_status) {
9994   case MAT_FACTOR_SCHUR_FACTORED:
9995     PetscCall(MatSolve(F->schur, rhs, sol));
9996     break;
9997   case MAT_FACTOR_SCHUR_INVERTED:
9998     PetscCall(MatMult(F->schur, rhs, sol));
9999     break;
10000   default:
10001     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10002   }
10003   PetscFunctionReturn(PETSC_SUCCESS);
10004 }
10005 
10006 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10007 #if PetscDefined(HAVE_CUDA)
10008 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10009 #endif
10010 
10011 /* Schur status updated in the interface */
10012 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10013 {
10014   Mat S = F->schur;
10015 
10016   PetscFunctionBegin;
10017   if (S) {
10018     PetscMPIInt size;
10019     PetscBool   isdense, isdensecuda;
10020 
10021     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10022     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10023     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10024     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10025     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10026     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10027     if (isdense) {
10028       PetscCall(MatSeqDenseInvertFactors_Private(S));
10029     } else if (isdensecuda) {
10030 #if defined(PETSC_HAVE_CUDA)
10031       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10032 #endif
10033     }
10034     // HIP??????????????
10035     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10036   }
10037   PetscFunctionReturn(PETSC_SUCCESS);
10038 }
10039 
10040 /*@
10041   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10042 
10043   Logically Collective
10044 
10045   Input Parameter:
10046 . F - the factored matrix obtained by calling `MatGetFactor()`
10047 
10048   Level: advanced
10049 
10050   Notes:
10051   Must be called after `MatFactorSetSchurIS()`.
10052 
10053   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10054 
10055 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10056 @*/
10057 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10058 {
10059   PetscFunctionBegin;
10060   PetscValidType(F, 1);
10061   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10062   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10063   PetscCall(MatFactorFactorizeSchurComplement(F));
10064   PetscCall(MatFactorInvertSchurComplement_Private(F));
10065   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10066   PetscFunctionReturn(PETSC_SUCCESS);
10067 }
10068 
10069 /*@
10070   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10071 
10072   Logically Collective
10073 
10074   Input Parameter:
10075 . F - the factored matrix obtained by calling `MatGetFactor()`
10076 
10077   Level: advanced
10078 
10079   Note:
10080   Must be called after `MatFactorSetSchurIS()`
10081 
10082 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10083 @*/
10084 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10085 {
10086   MatFactorInfo info;
10087 
10088   PetscFunctionBegin;
10089   PetscValidType(F, 1);
10090   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10091   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10092   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10093   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10094   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10095     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10096   } else {
10097     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10098   }
10099   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10100   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10101   PetscFunctionReturn(PETSC_SUCCESS);
10102 }
10103 
10104 /*@
10105   MatPtAP - Creates the matrix product $C = P^T * A * P$
10106 
10107   Neighbor-wise Collective
10108 
10109   Input Parameters:
10110 + A     - the matrix
10111 . P     - the projection matrix
10112 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10113 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
10114           if the result is a dense matrix this is irrelevant
10115 
10116   Output Parameter:
10117 . C - the product matrix
10118 
10119   Level: intermediate
10120 
10121   Notes:
10122   C will be created and must be destroyed by the user with `MatDestroy()`.
10123 
10124   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10125 
10126   Developer Note:
10127   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10128 
10129 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10130 @*/
10131 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10132 {
10133   PetscFunctionBegin;
10134   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10135   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10136 
10137   if (scall == MAT_INITIAL_MATRIX) {
10138     PetscCall(MatProductCreate(A, P, NULL, C));
10139     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10140     PetscCall(MatProductSetAlgorithm(*C, "default"));
10141     PetscCall(MatProductSetFill(*C, fill));
10142 
10143     (*C)->product->api_user = PETSC_TRUE;
10144     PetscCall(MatProductSetFromOptions(*C));
10145     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);
10146     PetscCall(MatProductSymbolic(*C));
10147   } else { /* scall == MAT_REUSE_MATRIX */
10148     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10149   }
10150 
10151   PetscCall(MatProductNumeric(*C));
10152   (*C)->symmetric = A->symmetric;
10153   (*C)->spd       = A->spd;
10154   PetscFunctionReturn(PETSC_SUCCESS);
10155 }
10156 
10157 /*@
10158   MatRARt - Creates the matrix product $C = R * A * R^T$
10159 
10160   Neighbor-wise Collective
10161 
10162   Input Parameters:
10163 + A     - the matrix
10164 . R     - the projection matrix
10165 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10166 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
10167           if the result is a dense matrix this is irrelevant
10168 
10169   Output Parameter:
10170 . C - the product matrix
10171 
10172   Level: intermediate
10173 
10174   Notes:
10175   C will be created and must be destroyed by the user with `MatDestroy()`.
10176 
10177   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10178 
10179   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10180   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10181   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
10182   We recommend using MatPtAP().
10183 
10184 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10185 @*/
10186 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10187 {
10188   PetscFunctionBegin;
10189   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10190   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10191 
10192   if (scall == MAT_INITIAL_MATRIX) {
10193     PetscCall(MatProductCreate(A, R, NULL, C));
10194     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10195     PetscCall(MatProductSetAlgorithm(*C, "default"));
10196     PetscCall(MatProductSetFill(*C, fill));
10197 
10198     (*C)->product->api_user = PETSC_TRUE;
10199     PetscCall(MatProductSetFromOptions(*C));
10200     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);
10201     PetscCall(MatProductSymbolic(*C));
10202   } else { /* scall == MAT_REUSE_MATRIX */
10203     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10204   }
10205 
10206   PetscCall(MatProductNumeric(*C));
10207   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10208   PetscFunctionReturn(PETSC_SUCCESS);
10209 }
10210 
10211 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10212 {
10213   PetscBool flg = PETSC_TRUE;
10214 
10215   PetscFunctionBegin;
10216   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10217   if (scall == MAT_INITIAL_MATRIX) {
10218     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10219     PetscCall(MatProductCreate(A, B, NULL, C));
10220     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10221     PetscCall(MatProductSetFill(*C, fill));
10222   } else { /* scall == MAT_REUSE_MATRIX */
10223     Mat_Product *product = (*C)->product;
10224 
10225     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10226     if (flg && product && product->type != ptype) {
10227       PetscCall(MatProductClear(*C));
10228       product = NULL;
10229     }
10230     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10231     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10232       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10233       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10234       product        = (*C)->product;
10235       product->fill  = fill;
10236       product->clear = PETSC_TRUE;
10237     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10238       flg = PETSC_FALSE;
10239       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10240     }
10241   }
10242   if (flg) {
10243     (*C)->product->api_user = PETSC_TRUE;
10244     PetscCall(MatProductSetType(*C, ptype));
10245     PetscCall(MatProductSetFromOptions(*C));
10246     PetscCall(MatProductSymbolic(*C));
10247   }
10248   PetscCall(MatProductNumeric(*C));
10249   PetscFunctionReturn(PETSC_SUCCESS);
10250 }
10251 
10252 /*@
10253   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10254 
10255   Neighbor-wise Collective
10256 
10257   Input Parameters:
10258 + A     - the left matrix
10259 . B     - the right matrix
10260 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10261 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10262           if the result is a dense matrix this is irrelevant
10263 
10264   Output Parameter:
10265 . C - the product matrix
10266 
10267   Notes:
10268   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10269 
10270   `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
10271   call to this function with `MAT_INITIAL_MATRIX`.
10272 
10273   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10274 
10275   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`,
10276   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10277 
10278   Example of Usage:
10279 .vb
10280      MatProductCreate(A,B,NULL,&C);
10281      MatProductSetType(C,MATPRODUCT_AB);
10282      MatProductSymbolic(C);
10283      MatProductNumeric(C); // compute C=A * B
10284      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10285      MatProductNumeric(C);
10286      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10287      MatProductNumeric(C);
10288 .ve
10289 
10290   Level: intermediate
10291 
10292 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10293 @*/
10294 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10295 {
10296   PetscFunctionBegin;
10297   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10298   PetscFunctionReturn(PETSC_SUCCESS);
10299 }
10300 
10301 /*@
10302   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10303 
10304   Neighbor-wise Collective
10305 
10306   Input Parameters:
10307 + A     - the left matrix
10308 . B     - the right matrix
10309 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10310 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10311 
10312   Output Parameter:
10313 . C - the product matrix
10314 
10315   Options Database Key:
10316 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10317               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10318               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10319 
10320   Level: intermediate
10321 
10322   Notes:
10323   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10324 
10325   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10326 
10327   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10328   actually needed.
10329 
10330   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10331   and for pairs of `MATMPIDENSE` matrices.
10332 
10333   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10334 
10335 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10336 @*/
10337 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10338 {
10339   PetscFunctionBegin;
10340   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10341   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10342   PetscFunctionReturn(PETSC_SUCCESS);
10343 }
10344 
10345 /*@
10346   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10347 
10348   Neighbor-wise Collective
10349 
10350   Input Parameters:
10351 + A     - the left matrix
10352 . B     - the right matrix
10353 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10354 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10355 
10356   Output Parameter:
10357 . C - the product matrix
10358 
10359   Level: intermediate
10360 
10361   Notes:
10362   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10363 
10364   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10365 
10366   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10367 
10368   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10369   actually needed.
10370 
10371   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10372   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10373 
10374 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10375 @*/
10376 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10377 {
10378   PetscFunctionBegin;
10379   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10380   PetscFunctionReturn(PETSC_SUCCESS);
10381 }
10382 
10383 /*@
10384   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10385 
10386   Neighbor-wise Collective
10387 
10388   Input Parameters:
10389 + A     - the left matrix
10390 . B     - the middle matrix
10391 . C     - the right matrix
10392 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10393 - 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
10394           if the result is a dense matrix this is irrelevant
10395 
10396   Output Parameter:
10397 . D - the product matrix
10398 
10399   Level: intermediate
10400 
10401   Notes:
10402   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10403 
10404   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10405 
10406   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10407 
10408   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10409   actually needed.
10410 
10411   If you have many matrices with the same non-zero structure to multiply, you
10412   should use `MAT_REUSE_MATRIX` in all calls but the first
10413 
10414 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10415 @*/
10416 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10417 {
10418   PetscFunctionBegin;
10419   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10420   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10421 
10422   if (scall == MAT_INITIAL_MATRIX) {
10423     PetscCall(MatProductCreate(A, B, C, D));
10424     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10425     PetscCall(MatProductSetAlgorithm(*D, "default"));
10426     PetscCall(MatProductSetFill(*D, fill));
10427 
10428     (*D)->product->api_user = PETSC_TRUE;
10429     PetscCall(MatProductSetFromOptions(*D));
10430     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,
10431                ((PetscObject)C)->type_name);
10432     PetscCall(MatProductSymbolic(*D));
10433   } else { /* user may change input matrices when REUSE */
10434     PetscCall(MatProductReplaceMats(A, B, C, *D));
10435   }
10436   PetscCall(MatProductNumeric(*D));
10437   PetscFunctionReturn(PETSC_SUCCESS);
10438 }
10439 
10440 /*@
10441   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10442 
10443   Collective
10444 
10445   Input Parameters:
10446 + mat      - the matrix
10447 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10448 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10449 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10450 
10451   Output Parameter:
10452 . matredundant - redundant matrix
10453 
10454   Level: advanced
10455 
10456   Notes:
10457   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10458   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10459 
10460   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10461   calling it.
10462 
10463   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10464 
10465 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10466 @*/
10467 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10468 {
10469   MPI_Comm       comm;
10470   PetscMPIInt    size;
10471   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10472   Mat_Redundant *redund     = NULL;
10473   PetscSubcomm   psubcomm   = NULL;
10474   MPI_Comm       subcomm_in = subcomm;
10475   Mat           *matseq;
10476   IS             isrow, iscol;
10477   PetscBool      newsubcomm = PETSC_FALSE;
10478 
10479   PetscFunctionBegin;
10480   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10481   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10482     PetscAssertPointer(*matredundant, 5);
10483     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10484   }
10485 
10486   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10487   if (size == 1 || nsubcomm == 1) {
10488     if (reuse == MAT_INITIAL_MATRIX) {
10489       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10490     } else {
10491       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");
10492       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10493     }
10494     PetscFunctionReturn(PETSC_SUCCESS);
10495   }
10496 
10497   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10498   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10499   MatCheckPreallocated(mat, 1);
10500 
10501   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10502   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10503     /* create psubcomm, then get subcomm */
10504     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10505     PetscCallMPI(MPI_Comm_size(comm, &size));
10506     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10507 
10508     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10509     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10510     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10511     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10512     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10513     newsubcomm = PETSC_TRUE;
10514     PetscCall(PetscSubcommDestroy(&psubcomm));
10515   }
10516 
10517   /* get isrow, iscol and a local sequential matrix matseq[0] */
10518   if (reuse == MAT_INITIAL_MATRIX) {
10519     mloc_sub = PETSC_DECIDE;
10520     nloc_sub = PETSC_DECIDE;
10521     if (bs < 1) {
10522       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10523       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10524     } else {
10525       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10526       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10527     }
10528     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10529     rstart = rend - mloc_sub;
10530     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10531     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10532     PetscCall(ISSetIdentity(iscol));
10533   } else { /* reuse == MAT_REUSE_MATRIX */
10534     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");
10535     /* retrieve subcomm */
10536     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10537     redund = (*matredundant)->redundant;
10538     isrow  = redund->isrow;
10539     iscol  = redund->iscol;
10540     matseq = redund->matseq;
10541   }
10542   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10543 
10544   /* get matredundant over subcomm */
10545   if (reuse == MAT_INITIAL_MATRIX) {
10546     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10547 
10548     /* create a supporting struct and attach it to C for reuse */
10549     PetscCall(PetscNew(&redund));
10550     (*matredundant)->redundant = redund;
10551     redund->isrow              = isrow;
10552     redund->iscol              = iscol;
10553     redund->matseq             = matseq;
10554     if (newsubcomm) {
10555       redund->subcomm = subcomm;
10556     } else {
10557       redund->subcomm = MPI_COMM_NULL;
10558     }
10559   } else {
10560     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10561   }
10562 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10563   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10564     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10565     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10566   }
10567 #endif
10568   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10569   PetscFunctionReturn(PETSC_SUCCESS);
10570 }
10571 
10572 /*@C
10573   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10574   a given `Mat`. Each submatrix can span multiple procs.
10575 
10576   Collective
10577 
10578   Input Parameters:
10579 + mat     - the matrix
10580 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10581 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10582 
10583   Output Parameter:
10584 . subMat - parallel sub-matrices each spanning a given `subcomm`
10585 
10586   Level: advanced
10587 
10588   Notes:
10589   The submatrix partition across processors is dictated by `subComm` a
10590   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10591   is not restricted to be grouped with consecutive original MPI processes.
10592 
10593   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10594   map directly to the layout of the original matrix [wrt the local
10595   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10596   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10597   the `subMat`. However the offDiagMat looses some columns - and this is
10598   reconstructed with `MatSetValues()`
10599 
10600   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10601 
10602 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10603 @*/
10604 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10605 {
10606   PetscMPIInt commsize, subCommSize;
10607 
10608   PetscFunctionBegin;
10609   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10610   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10611   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10612 
10613   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");
10614   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10615   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10616   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10617   PetscFunctionReturn(PETSC_SUCCESS);
10618 }
10619 
10620 /*@
10621   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10622 
10623   Not Collective
10624 
10625   Input Parameters:
10626 + mat   - matrix to extract local submatrix from
10627 . isrow - local row indices for submatrix
10628 - iscol - local column indices for submatrix
10629 
10630   Output Parameter:
10631 . submat - the submatrix
10632 
10633   Level: intermediate
10634 
10635   Notes:
10636   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10637 
10638   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10639   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10640 
10641   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10642   `MatSetValuesBlockedLocal()` will also be implemented.
10643 
10644   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10645   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10646 
10647 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10648 @*/
10649 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10650 {
10651   PetscFunctionBegin;
10652   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10653   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10654   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10655   PetscCheckSameComm(isrow, 2, iscol, 3);
10656   PetscAssertPointer(submat, 4);
10657   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10658 
10659   if (mat->ops->getlocalsubmatrix) {
10660     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10661   } else {
10662     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10663   }
10664   PetscFunctionReturn(PETSC_SUCCESS);
10665 }
10666 
10667 /*@
10668   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10669 
10670   Not Collective
10671 
10672   Input Parameters:
10673 + mat    - matrix to extract local submatrix from
10674 . isrow  - local row indices for submatrix
10675 . iscol  - local column indices for submatrix
10676 - submat - the submatrix
10677 
10678   Level: intermediate
10679 
10680 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10681 @*/
10682 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10683 {
10684   PetscFunctionBegin;
10685   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10686   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10687   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10688   PetscCheckSameComm(isrow, 2, iscol, 3);
10689   PetscAssertPointer(submat, 4);
10690   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10691 
10692   if (mat->ops->restorelocalsubmatrix) {
10693     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10694   } else {
10695     PetscCall(MatDestroy(submat));
10696   }
10697   *submat = NULL;
10698   PetscFunctionReturn(PETSC_SUCCESS);
10699 }
10700 
10701 /*@
10702   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10703 
10704   Collective
10705 
10706   Input Parameter:
10707 . mat - the matrix
10708 
10709   Output Parameter:
10710 . is - if any rows have zero diagonals this contains the list of them
10711 
10712   Level: developer
10713 
10714 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10715 @*/
10716 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10717 {
10718   PetscFunctionBegin;
10719   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10720   PetscValidType(mat, 1);
10721   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10722   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10723 
10724   if (!mat->ops->findzerodiagonals) {
10725     Vec                diag;
10726     const PetscScalar *a;
10727     PetscInt          *rows;
10728     PetscInt           rStart, rEnd, r, nrow = 0;
10729 
10730     PetscCall(MatCreateVecs(mat, &diag, NULL));
10731     PetscCall(MatGetDiagonal(mat, diag));
10732     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10733     PetscCall(VecGetArrayRead(diag, &a));
10734     for (r = 0; r < rEnd - rStart; ++r)
10735       if (a[r] == 0.0) ++nrow;
10736     PetscCall(PetscMalloc1(nrow, &rows));
10737     nrow = 0;
10738     for (r = 0; r < rEnd - rStart; ++r)
10739       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10740     PetscCall(VecRestoreArrayRead(diag, &a));
10741     PetscCall(VecDestroy(&diag));
10742     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10743   } else {
10744     PetscUseTypeMethod(mat, findzerodiagonals, is);
10745   }
10746   PetscFunctionReturn(PETSC_SUCCESS);
10747 }
10748 
10749 /*@
10750   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10751 
10752   Collective
10753 
10754   Input Parameter:
10755 . mat - the matrix
10756 
10757   Output Parameter:
10758 . is - contains the list of rows with off block diagonal entries
10759 
10760   Level: developer
10761 
10762 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10763 @*/
10764 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10765 {
10766   PetscFunctionBegin;
10767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10768   PetscValidType(mat, 1);
10769   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10770   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10771 
10772   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10773   PetscFunctionReturn(PETSC_SUCCESS);
10774 }
10775 
10776 /*@C
10777   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10778 
10779   Collective; No Fortran Support
10780 
10781   Input Parameter:
10782 . mat - the matrix
10783 
10784   Output Parameter:
10785 . values - the block inverses in column major order (FORTRAN-like)
10786 
10787   Level: advanced
10788 
10789   Notes:
10790   The size of the blocks is determined by the block size of the matrix.
10791 
10792   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10793 
10794   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10795 
10796 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10797 @*/
10798 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10799 {
10800   PetscFunctionBegin;
10801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10802   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10803   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10804   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10805   PetscFunctionReturn(PETSC_SUCCESS);
10806 }
10807 
10808 /*@
10809   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10810 
10811   Collective; No Fortran Support
10812 
10813   Input Parameters:
10814 + mat     - the matrix
10815 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10816 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10817 
10818   Output Parameter:
10819 . values - the block inverses in column major order (FORTRAN-like)
10820 
10821   Level: advanced
10822 
10823   Notes:
10824   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10825 
10826   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10827 
10828 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10829 @*/
10830 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10831 {
10832   PetscFunctionBegin;
10833   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10834   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10835   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10836   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10837   PetscFunctionReturn(PETSC_SUCCESS);
10838 }
10839 
10840 /*@
10841   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10842 
10843   Collective
10844 
10845   Input Parameters:
10846 + A - the matrix
10847 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10848 
10849   Level: advanced
10850 
10851   Note:
10852   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10853 
10854 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10855 @*/
10856 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10857 {
10858   const PetscScalar *vals;
10859   PetscInt          *dnnz;
10860   PetscInt           m, rstart, rend, bs, i, j;
10861 
10862   PetscFunctionBegin;
10863   PetscCall(MatInvertBlockDiagonal(A, &vals));
10864   PetscCall(MatGetBlockSize(A, &bs));
10865   PetscCall(MatGetLocalSize(A, &m, NULL));
10866   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10867   PetscCall(PetscMalloc1(m / bs, &dnnz));
10868   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10869   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10870   PetscCall(PetscFree(dnnz));
10871   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10872   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10873   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10874   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10875   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10876   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10877   PetscFunctionReturn(PETSC_SUCCESS);
10878 }
10879 
10880 /*@C
10881   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10882   via `MatTransposeColoringCreate()`.
10883 
10884   Collective
10885 
10886   Input Parameter:
10887 . c - coloring context
10888 
10889   Level: intermediate
10890 
10891 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10892 @*/
10893 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10894 {
10895   MatTransposeColoring matcolor = *c;
10896 
10897   PetscFunctionBegin;
10898   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10899   if (--((PetscObject)matcolor)->refct > 0) {
10900     matcolor = NULL;
10901     PetscFunctionReturn(PETSC_SUCCESS);
10902   }
10903 
10904   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10905   PetscCall(PetscFree(matcolor->rows));
10906   PetscCall(PetscFree(matcolor->den2sp));
10907   PetscCall(PetscFree(matcolor->colorforcol));
10908   PetscCall(PetscFree(matcolor->columns));
10909   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10910   PetscCall(PetscHeaderDestroy(c));
10911   PetscFunctionReturn(PETSC_SUCCESS);
10912 }
10913 
10914 /*@
10915   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10916   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10917   `MatTransposeColoring` to sparse `B`.
10918 
10919   Collective
10920 
10921   Input Parameters:
10922 + coloring - coloring context created with `MatTransposeColoringCreate()`
10923 - B        - sparse matrix
10924 
10925   Output Parameter:
10926 . Btdense - dense matrix $B^T$
10927 
10928   Level: developer
10929 
10930   Note:
10931   These are used internally for some implementations of `MatRARt()`
10932 
10933 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10934 @*/
10935 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10936 {
10937   PetscFunctionBegin;
10938   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10939   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10940   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10941 
10942   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10943   PetscFunctionReturn(PETSC_SUCCESS);
10944 }
10945 
10946 /*@
10947   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10948   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10949   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10950   $C_{sp}$ from $C_{den}$.
10951 
10952   Collective
10953 
10954   Input Parameters:
10955 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10956 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10957 
10958   Output Parameter:
10959 . Csp - sparse matrix
10960 
10961   Level: developer
10962 
10963   Note:
10964   These are used internally for some implementations of `MatRARt()`
10965 
10966 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10967 @*/
10968 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10969 {
10970   PetscFunctionBegin;
10971   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10972   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10973   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10974 
10975   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10976   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10977   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10978   PetscFunctionReturn(PETSC_SUCCESS);
10979 }
10980 
10981 /*@
10982   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10983 
10984   Collective
10985 
10986   Input Parameters:
10987 + mat        - the matrix product C
10988 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10989 
10990   Output Parameter:
10991 . color - the new coloring context
10992 
10993   Level: intermediate
10994 
10995 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10996           `MatTransColoringApplyDenToSp()`
10997 @*/
10998 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10999 {
11000   MatTransposeColoring c;
11001   MPI_Comm             comm;
11002 
11003   PetscFunctionBegin;
11004   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11005   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11006   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11007 
11008   c->ctype = iscoloring->ctype;
11009   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11010 
11011   *color = c;
11012   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11013   PetscFunctionReturn(PETSC_SUCCESS);
11014 }
11015 
11016 /*@
11017   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11018   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11019 
11020   Not Collective
11021 
11022   Input Parameter:
11023 . mat - the matrix
11024 
11025   Output Parameter:
11026 . state - the current state
11027 
11028   Level: intermediate
11029 
11030   Notes:
11031   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11032   different matrices
11033 
11034   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11035 
11036   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11037 
11038 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11039 @*/
11040 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11041 {
11042   PetscFunctionBegin;
11043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11044   *state = mat->nonzerostate;
11045   PetscFunctionReturn(PETSC_SUCCESS);
11046 }
11047 
11048 /*@
11049   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11050   matrices from each processor
11051 
11052   Collective
11053 
11054   Input Parameters:
11055 + comm   - the communicators the parallel matrix will live on
11056 . seqmat - the input sequential matrices
11057 . n      - number of local columns (or `PETSC_DECIDE`)
11058 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11059 
11060   Output Parameter:
11061 . mpimat - the parallel matrix generated
11062 
11063   Level: developer
11064 
11065   Note:
11066   The number of columns of the matrix in EACH processor MUST be the same.
11067 
11068 .seealso: [](ch_matrices), `Mat`
11069 @*/
11070 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11071 {
11072   PetscMPIInt size;
11073 
11074   PetscFunctionBegin;
11075   PetscCallMPI(MPI_Comm_size(comm, &size));
11076   if (size == 1) {
11077     if (reuse == MAT_INITIAL_MATRIX) {
11078       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11079     } else {
11080       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11081     }
11082     PetscFunctionReturn(PETSC_SUCCESS);
11083   }
11084 
11085   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");
11086 
11087   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11088   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11089   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11090   PetscFunctionReturn(PETSC_SUCCESS);
11091 }
11092 
11093 /*@
11094   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11095 
11096   Collective
11097 
11098   Input Parameters:
11099 + A - the matrix to create subdomains from
11100 - N - requested number of subdomains
11101 
11102   Output Parameters:
11103 + n   - number of subdomains resulting on this MPI process
11104 - iss - `IS` list with indices of subdomains on this MPI process
11105 
11106   Level: advanced
11107 
11108   Note:
11109   The number of subdomains must be smaller than the communicator size
11110 
11111 .seealso: [](ch_matrices), `Mat`, `IS`
11112 @*/
11113 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11114 {
11115   MPI_Comm    comm, subcomm;
11116   PetscMPIInt size, rank, color;
11117   PetscInt    rstart, rend, k;
11118 
11119   PetscFunctionBegin;
11120   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11121   PetscCallMPI(MPI_Comm_size(comm, &size));
11122   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11123   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);
11124   *n    = 1;
11125   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11126   color = rank / k;
11127   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11128   PetscCall(PetscMalloc1(1, iss));
11129   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11130   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11131   PetscCallMPI(MPI_Comm_free(&subcomm));
11132   PetscFunctionReturn(PETSC_SUCCESS);
11133 }
11134 
11135 /*@
11136   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11137 
11138   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11139   If they are not the same, uses `MatMatMatMult()`.
11140 
11141   Once the coarse grid problem is constructed, correct for interpolation operators
11142   that are not of full rank, which can legitimately happen in the case of non-nested
11143   geometric multigrid.
11144 
11145   Input Parameters:
11146 + restrct     - restriction operator
11147 . dA          - fine grid matrix
11148 . interpolate - interpolation operator
11149 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11150 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
11151 
11152   Output Parameter:
11153 . A - the Galerkin coarse matrix
11154 
11155   Options Database Key:
11156 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11157 
11158   Level: developer
11159 
11160 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11161 @*/
11162 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11163 {
11164   IS  zerorows;
11165   Vec diag;
11166 
11167   PetscFunctionBegin;
11168   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11169   /* Construct the coarse grid matrix */
11170   if (interpolate == restrct) {
11171     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11172   } else {
11173     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11174   }
11175 
11176   /* If the interpolation matrix is not of full rank, A will have zero rows.
11177      This can legitimately happen in the case of non-nested geometric multigrid.
11178      In that event, we set the rows of the matrix to the rows of the identity,
11179      ignoring the equations (as the RHS will also be zero). */
11180 
11181   PetscCall(MatFindZeroRows(*A, &zerorows));
11182 
11183   if (zerorows != NULL) { /* if there are any zero rows */
11184     PetscCall(MatCreateVecs(*A, &diag, NULL));
11185     PetscCall(MatGetDiagonal(*A, diag));
11186     PetscCall(VecISSet(diag, zerorows, 1.0));
11187     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11188     PetscCall(VecDestroy(&diag));
11189     PetscCall(ISDestroy(&zerorows));
11190   }
11191   PetscFunctionReturn(PETSC_SUCCESS);
11192 }
11193 
11194 /*@C
11195   MatSetOperation - Allows user to set a matrix operation for any matrix type
11196 
11197   Logically Collective
11198 
11199   Input Parameters:
11200 + mat - the matrix
11201 . op  - the name of the operation
11202 - f   - the function that provides the operation
11203 
11204   Level: developer
11205 
11206   Example Usage:
11207 .vb
11208   extern PetscErrorCode usermult(Mat, Vec, Vec);
11209 
11210   PetscCall(MatCreateXXX(comm, ..., &A));
11211   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11212 .ve
11213 
11214   Notes:
11215   See the file `include/petscmat.h` for a complete list of matrix
11216   operations, which all have the form MATOP_<OPERATION>, where
11217   <OPERATION> is the name (in all capital letters) of the
11218   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11219 
11220   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11221   sequence as the usual matrix interface routines, since they
11222   are intended to be accessed via the usual matrix interface
11223   routines, e.g.,
11224 .vb
11225   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11226 .ve
11227 
11228   In particular each function MUST return `PETSC_SUCCESS` on success and
11229   nonzero on failure.
11230 
11231   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11232 
11233 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11234 @*/
11235 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11236 {
11237   PetscFunctionBegin;
11238   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11239   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11240   (((void (**)(void))mat->ops)[op]) = f;
11241   PetscFunctionReturn(PETSC_SUCCESS);
11242 }
11243 
11244 /*@C
11245   MatGetOperation - Gets a matrix operation for any matrix type.
11246 
11247   Not Collective
11248 
11249   Input Parameters:
11250 + mat - the matrix
11251 - op  - the name of the operation
11252 
11253   Output Parameter:
11254 . f - the function that provides the operation
11255 
11256   Level: developer
11257 
11258   Example Usage:
11259 .vb
11260   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11261 
11262   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11263 .ve
11264 
11265   Notes:
11266   See the file include/petscmat.h for a complete list of matrix
11267   operations, which all have the form MATOP_<OPERATION>, where
11268   <OPERATION> is the name (in all capital letters) of the
11269   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11270 
11271   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11272 
11273 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11274 @*/
11275 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11276 {
11277   PetscFunctionBegin;
11278   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11279   *f = (((void (**)(void))mat->ops)[op]);
11280   PetscFunctionReturn(PETSC_SUCCESS);
11281 }
11282 
11283 /*@
11284   MatHasOperation - Determines whether the given matrix supports the particular operation.
11285 
11286   Not Collective
11287 
11288   Input Parameters:
11289 + mat - the matrix
11290 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11291 
11292   Output Parameter:
11293 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11294 
11295   Level: advanced
11296 
11297   Note:
11298   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11299 
11300 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11301 @*/
11302 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11303 {
11304   PetscFunctionBegin;
11305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11306   PetscAssertPointer(has, 3);
11307   if (mat->ops->hasoperation) {
11308     PetscUseTypeMethod(mat, hasoperation, op, has);
11309   } else {
11310     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11311     else {
11312       *has = PETSC_FALSE;
11313       if (op == MATOP_CREATE_SUBMATRIX) {
11314         PetscMPIInt size;
11315 
11316         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11317         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11318       }
11319     }
11320   }
11321   PetscFunctionReturn(PETSC_SUCCESS);
11322 }
11323 
11324 /*@
11325   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11326 
11327   Collective
11328 
11329   Input Parameter:
11330 . mat - the matrix
11331 
11332   Output Parameter:
11333 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11334 
11335   Level: beginner
11336 
11337 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11338 @*/
11339 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11340 {
11341   PetscFunctionBegin;
11342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11343   PetscValidType(mat, 1);
11344   PetscAssertPointer(cong, 2);
11345   if (!mat->rmap || !mat->cmap) {
11346     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11347     PetscFunctionReturn(PETSC_SUCCESS);
11348   }
11349   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11350     PetscCall(PetscLayoutSetUp(mat->rmap));
11351     PetscCall(PetscLayoutSetUp(mat->cmap));
11352     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11353     if (*cong) mat->congruentlayouts = 1;
11354     else mat->congruentlayouts = 0;
11355   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11356   PetscFunctionReturn(PETSC_SUCCESS);
11357 }
11358 
11359 PetscErrorCode MatSetInf(Mat A)
11360 {
11361   PetscFunctionBegin;
11362   PetscUseTypeMethod(A, setinf);
11363   PetscFunctionReturn(PETSC_SUCCESS);
11364 }
11365 
11366 /*@
11367   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
11368   and possibly removes small values from the graph structure.
11369 
11370   Collective
11371 
11372   Input Parameters:
11373 + A       - the matrix
11374 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11375 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11376 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11377 . num_idx - size of 'index' array
11378 - index   - array of block indices to use for graph strength of connection weight
11379 
11380   Output Parameter:
11381 . graph - the resulting graph
11382 
11383   Level: advanced
11384 
11385 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11386 @*/
11387 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11388 {
11389   PetscFunctionBegin;
11390   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11391   PetscValidType(A, 1);
11392   PetscValidLogicalCollectiveBool(A, scale, 3);
11393   PetscAssertPointer(graph, 7);
11394   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11395   PetscFunctionReturn(PETSC_SUCCESS);
11396 }
11397 
11398 /*@
11399   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11400   meaning the same memory is used for the matrix, and no new memory is allocated.
11401 
11402   Collective
11403 
11404   Input Parameters:
11405 + A    - the matrix
11406 - 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
11407 
11408   Level: intermediate
11409 
11410   Developer Note:
11411   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11412   of the arrays in the data structure are unneeded.
11413 
11414 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11415 @*/
11416 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11417 {
11418   PetscFunctionBegin;
11419   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11420   PetscUseTypeMethod(A, eliminatezeros, keep);
11421   PetscFunctionReturn(PETSC_SUCCESS);
11422 }
11423