xref: /petsc/src/mat/interface/matrix.c (revision 789736e13dc7600624280f2f1d112db076e5d354)
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_CreateGraph;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52   MatSetRandom - Sets all components of a matrix to random numbers.
53 
54   Logically Collective
55 
56   Input Parameters:
57 + x    - the matrix
58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61   Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68   Level: intermediate
69 
70   Notes:
71   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
72 
73   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
74 
75   It generates an error if used on unassembled sparse matrices that have not been preallocated.
76 
77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108   MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type
109 
110   Logically Collective
111 
112   Input Parameter:
113 . A - A matrix in unassembled, hash table form
114 
115   Output Parameter:
116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()`
117 
118   Example:
119 .vb
120      PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B));
121      PetscCall(MatCopyHashToXAIJ(A, B));
122 .ve
123 
124   Level: advanced
125 
126   Notes:
127   If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled
128 
129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE`
130 @*/
131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
135   PetscUseTypeMethod(A, copyhashtoxaij, B);
136   PetscFunctionReturn(PETSC_SUCCESS);
137 }
138 
139 /*@
140   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
141 
142   Logically Collective
143 
144   Input Parameter:
145 . mat - the factored matrix
146 
147   Output Parameters:
148 + pivot - the pivot value computed
149 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
150          the share the matrix
151 
152   Level: advanced
153 
154   Notes:
155   This routine does not work for factorizations done with external packages.
156 
157   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
158 
159   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
160 
161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
163 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
164 @*/
165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
166 {
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
169   PetscAssertPointer(pivot, 2);
170   PetscAssertPointer(row, 3);
171   *pivot = mat->factorerror_zeropivot_value;
172   *row   = mat->factorerror_zeropivot_row;
173   PetscFunctionReturn(PETSC_SUCCESS);
174 }
175 
176 /*@
177   MatFactorGetError - gets the error code from a factorization
178 
179   Logically Collective
180 
181   Input Parameter:
182 . mat - the factored matrix
183 
184   Output Parameter:
185 . err - the error code
186 
187   Level: advanced
188 
189   Note:
190   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
191 
192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
193           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
194 @*/
195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
196 {
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
199   PetscAssertPointer(err, 2);
200   *err = mat->factorerrortype;
201   PetscFunctionReturn(PETSC_SUCCESS);
202 }
203 
204 /*@
205   MatFactorClearError - clears the error code in a factorization
206 
207   Logically Collective
208 
209   Input Parameter:
210 . mat - the factored matrix
211 
212   Level: developer
213 
214   Note:
215   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
216 
217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
218           `MatGetErrorCode()`, `MatFactorError`
219 @*/
220 PetscErrorCode MatFactorClearError(Mat mat)
221 {
222   PetscFunctionBegin;
223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
224   mat->factorerrortype             = MAT_FACTOR_NOERROR;
225   mat->factorerror_zeropivot_value = 0.0;
226   mat->factorerror_zeropivot_row   = 0;
227   PetscFunctionReturn(PETSC_SUCCESS);
228 }
229 
230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
231 {
232   Vec                r, l;
233   const PetscScalar *al;
234   PetscInt           i, nz, gnz, N, n, st;
235 
236   PetscFunctionBegin;
237   PetscCall(MatCreateVecs(mat, &r, &l));
238   if (!cols) { /* nonzero rows */
239     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
240     PetscCall(MatGetSize(mat, &N, NULL));
241     PetscCall(MatGetLocalSize(mat, &n, NULL));
242     PetscCall(VecSet(l, 0.0));
243     PetscCall(VecSetRandom(r, NULL));
244     PetscCall(MatMult(mat, r, l));
245     PetscCall(VecGetArrayRead(l, &al));
246   } else { /* nonzero columns */
247     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
248     PetscCall(MatGetSize(mat, NULL, &N));
249     PetscCall(MatGetLocalSize(mat, NULL, &n));
250     PetscCall(VecSet(r, 0.0));
251     PetscCall(VecSetRandom(l, NULL));
252     PetscCall(MatMultTranspose(mat, l, r));
253     PetscCall(VecGetArrayRead(r, &al));
254   }
255   if (tol <= 0.0) {
256     for (i = 0, nz = 0; i < n; i++)
257       if (al[i] != 0.0) nz++;
258   } else {
259     for (i = 0, nz = 0; i < n; i++)
260       if (PetscAbsScalar(al[i]) > tol) nz++;
261   }
262   PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
263   if (gnz != N) {
264     PetscInt *nzr;
265     PetscCall(PetscMalloc1(nz, &nzr));
266     if (nz) {
267       if (tol < 0) {
268         for (i = 0, nz = 0; i < n; i++)
269           if (al[i] != 0.0) nzr[nz++] = i + st;
270       } else {
271         for (i = 0, nz = 0; i < n; i++)
272           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
273       }
274     }
275     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
276   } else *nonzero = NULL;
277   if (!cols) { /* nonzero rows */
278     PetscCall(VecRestoreArrayRead(l, &al));
279   } else {
280     PetscCall(VecRestoreArrayRead(r, &al));
281   }
282   PetscCall(VecDestroy(&l));
283   PetscCall(VecDestroy(&r));
284   PetscFunctionReturn(PETSC_SUCCESS);
285 }
286 
287 /*@
288   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
289 
290   Input Parameter:
291 . mat - the matrix
292 
293   Output Parameter:
294 . keptrows - the rows that are not completely zero
295 
296   Level: intermediate
297 
298   Note:
299   `keptrows` is set to `NULL` if all rows are nonzero.
300 
301   Developer Note:
302   If `keptrows` is not `NULL`, it must be sorted.
303 
304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
305  @*/
306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
307 {
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
310   PetscValidType(mat, 1);
311   PetscAssertPointer(keptrows, 2);
312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
314   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
315   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
316   if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatFindZeroRows - Locate all rows that are completely zero in the matrix
322 
323   Input Parameter:
324 . mat - the matrix
325 
326   Output Parameter:
327 . zerorows - the rows that are completely zero
328 
329   Level: intermediate
330 
331   Note:
332   `zerorows` is set to `NULL` if no rows are zero.
333 
334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
335  @*/
336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
337 {
338   IS       keptrows;
339   PetscInt m, n;
340 
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
343   PetscValidType(mat, 1);
344   PetscAssertPointer(zerorows, 2);
345   PetscCall(MatFindNonzeroRows(mat, &keptrows));
346   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
347      In keeping with this convention, we set zerorows to NULL if there are no zero
348      rows. */
349   if (keptrows == NULL) {
350     *zerorows = NULL;
351   } else {
352     PetscCall(MatGetOwnershipRange(mat, &m, &n));
353     PetscCall(ISComplement(keptrows, m, n, zerorows));
354     PetscCall(ISDestroy(&keptrows));
355   }
356   PetscFunctionReturn(PETSC_SUCCESS);
357 }
358 
359 /*@
360   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
361 
362   Not Collective
363 
364   Input Parameter:
365 . A - the matrix
366 
367   Output Parameter:
368 . a - the diagonal part (which is a SEQUENTIAL matrix)
369 
370   Level: advanced
371 
372   Notes:
373   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
374 
375   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
376 
377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
378 @*/
379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
380 {
381   PetscFunctionBegin;
382   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
383   PetscValidType(A, 1);
384   PetscAssertPointer(a, 2);
385   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
386   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
387   else {
388     PetscMPIInt size;
389 
390     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
391     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
392     *a = A;
393   }
394   PetscFunctionReturn(PETSC_SUCCESS);
395 }
396 
397 /*@
398   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
399 
400   Collective
401 
402   Input Parameter:
403 . mat - the matrix
404 
405   Output Parameter:
406 . trace - the sum of the diagonal entries
407 
408   Level: advanced
409 
410 .seealso: [](ch_matrices), `Mat`
411 @*/
412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
413 {
414   Vec diag;
415 
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
418   PetscAssertPointer(trace, 2);
419   PetscCall(MatCreateVecs(mat, &diag, NULL));
420   PetscCall(MatGetDiagonal(mat, diag));
421   PetscCall(VecSum(diag, trace));
422   PetscCall(VecDestroy(&diag));
423   PetscFunctionReturn(PETSC_SUCCESS);
424 }
425 
426 /*@
427   MatRealPart - Zeros out the imaginary part of the matrix
428 
429   Logically Collective
430 
431   Input Parameter:
432 . mat - the matrix
433 
434   Level: advanced
435 
436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
437 @*/
438 PetscErrorCode MatRealPart(Mat mat)
439 {
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
442   PetscValidType(mat, 1);
443   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
444   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
445   MatCheckPreallocated(mat, 1);
446   PetscUseTypeMethod(mat, realpart);
447   PetscFunctionReturn(PETSC_SUCCESS);
448 }
449 
450 /*@C
451   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
452 
453   Collective
454 
455   Input Parameter:
456 . mat - the matrix
457 
458   Output Parameters:
459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
460 - ghosts  - the global indices of the ghost points
461 
462   Level: advanced
463 
464   Note:
465   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
466 
467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
468 @*/
469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
470 {
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
473   PetscValidType(mat, 1);
474   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
475   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
476   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
477   else {
478     if (nghosts) *nghosts = 0;
479     if (ghosts) *ghosts = NULL;
480   }
481   PetscFunctionReturn(PETSC_SUCCESS);
482 }
483 
484 /*@
485   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
486 
487   Logically Collective
488 
489   Input Parameter:
490 . mat - the matrix
491 
492   Level: advanced
493 
494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
495 @*/
496 PetscErrorCode MatImaginaryPart(Mat mat)
497 {
498   PetscFunctionBegin;
499   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
500   PetscValidType(mat, 1);
501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
503   MatCheckPreallocated(mat, 1);
504   PetscUseTypeMethod(mat, imaginarypart);
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507 
508 /*@
509   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
510 
511   Not Collective
512 
513   Input Parameter:
514 . mat - the matrix
515 
516   Output Parameters:
517 + missing - is any diagonal entry missing
518 - dd      - first diagonal entry that is missing (optional) on this process
519 
520   Level: advanced
521 
522   Note:
523   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
524 
525 .seealso: [](ch_matrices), `Mat`
526 @*/
527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
528 {
529   PetscFunctionBegin;
530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
531   PetscValidType(mat, 1);
532   PetscAssertPointer(missing, 2);
533   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
534   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
535   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
536   PetscFunctionReturn(PETSC_SUCCESS);
537 }
538 
539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
540 /*@C
541   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
542   for each row that you get to ensure that your application does
543   not bleed memory.
544 
545   Not Collective
546 
547   Input Parameters:
548 + mat - the matrix
549 - row - the row to get
550 
551   Output Parameters:
552 + ncols - if not `NULL`, the number of nonzeros in `row`
553 . cols  - if not `NULL`, the column numbers
554 - vals  - if not `NULL`, the numerical values
555 
556   Level: advanced
557 
558   Notes:
559   This routine is provided for people who need to have direct access
560   to the structure of a matrix.  We hope that we provide enough
561   high-level matrix routines that few users will need it.
562 
563   `MatGetRow()` always returns 0-based column indices, regardless of
564   whether the internal representation is 0-based (default) or 1-based.
565 
566   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
567   not wish to extract these quantities.
568 
569   The user can only examine the values extracted with `MatGetRow()`;
570   the values CANNOT be altered.  To change the matrix entries, one
571   must use `MatSetValues()`.
572 
573   You can only have one call to `MatGetRow()` outstanding for a particular
574   matrix at a time, per processor. `MatGetRow()` can only obtain rows
575   associated with the given processor, it cannot get rows from the
576   other processors; for that we suggest using `MatCreateSubMatrices()`, then
577   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
578   is in the global number of rows.
579 
580   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
581 
582   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
583 
584   Fortran Note:
585 .vb
586   PetscInt, pointer :: cols(:)
587   PetscScalar, pointer :: vals(:)
588 .ve
589 
590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
591 @*/
592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
593 {
594   PetscInt incols;
595 
596   PetscFunctionBegin;
597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
598   PetscValidType(mat, 1);
599   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
600   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
601   MatCheckPreallocated(mat, 1);
602   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);
603   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
604   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
605   if (ncols) *ncols = incols;
606   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
607   PetscFunctionReturn(PETSC_SUCCESS);
608 }
609 
610 /*@
611   MatConjugate - replaces the matrix values with their complex conjugates
612 
613   Logically Collective
614 
615   Input Parameter:
616 . mat - the matrix
617 
618   Level: advanced
619 
620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
621 @*/
622 PetscErrorCode MatConjugate(Mat mat)
623 {
624   PetscFunctionBegin;
625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
626   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
627   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
628     PetscUseTypeMethod(mat, conjugate);
629     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
630   }
631   PetscFunctionReturn(PETSC_SUCCESS);
632 }
633 
634 /*@C
635   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
636 
637   Not Collective
638 
639   Input Parameters:
640 + mat   - the matrix
641 . row   - the row to get
642 . ncols - the number of nonzeros
643 . cols  - the columns of the nonzeros
644 - vals  - if nonzero the column values
645 
646   Level: advanced
647 
648   Notes:
649   This routine should be called after you have finished examining the entries.
650 
651   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
652   us of the array after it has been restored. If you pass `NULL`, it will
653   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
654 
655   Fortran Note:
656 .vb
657   PetscInt, pointer :: cols(:)
658   PetscScalar, pointer :: vals(:)
659 .ve
660 
661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
662 @*/
663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
664 {
665   PetscFunctionBegin;
666   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
667   if (ncols) PetscAssertPointer(ncols, 3);
668   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
669   PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
670   if (ncols) *ncols = 0;
671   if (cols) *cols = NULL;
672   if (vals) *vals = NULL;
673   PetscFunctionReturn(PETSC_SUCCESS);
674 }
675 
676 /*@
677   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
678   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
679 
680   Not Collective
681 
682   Input Parameter:
683 . mat - the matrix
684 
685   Level: advanced
686 
687   Note:
688   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.
689 
690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   PetscTryTypeMethod(mat, getrowuppertriangular);
701   PetscFunctionReturn(PETSC_SUCCESS);
702 }
703 
704 /*@
705   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
706 
707   Not Collective
708 
709   Input Parameter:
710 . mat - the matrix
711 
712   Level: advanced
713 
714   Note:
715   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
716 
717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
718 @*/
719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
720 {
721   PetscFunctionBegin;
722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
723   PetscValidType(mat, 1);
724   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
725   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
726   MatCheckPreallocated(mat, 1);
727   PetscTryTypeMethod(mat, restorerowuppertriangular);
728   PetscFunctionReturn(PETSC_SUCCESS);
729 }
730 
731 /*@
732   MatSetOptionsPrefix - Sets the prefix used for searching for all
733   `Mat` options in the database.
734 
735   Logically Collective
736 
737   Input Parameters:
738 + A      - the matrix
739 - prefix - the prefix to prepend to all option names
740 
741   Level: advanced
742 
743   Notes:
744   A hyphen (-) must NOT be given at the beginning of the prefix name.
745   The first character of all runtime options is AUTOMATICALLY the hyphen.
746 
747   This is NOT used for options for the factorization of the matrix. Normally the
748   prefix is automatically passed in from the PC calling the factorization. To set
749   it directly use  `MatSetOptionsPrefixFactor()`
750 
751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
752 @*/
753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
754 {
755   PetscFunctionBegin;
756   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
757   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
758   PetscTryMethod(A, "MatSetOptionsPrefix_C", (Mat, const char[]), (A, prefix));
759   PetscFunctionReturn(PETSC_SUCCESS);
760 }
761 
762 /*@
763   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
764   for matrices created with `MatGetFactor()`
765 
766   Logically Collective
767 
768   Input Parameters:
769 + A      - the matrix
770 - prefix - the prefix to prepend to all option names for the factored matrix
771 
772   Level: developer
773 
774   Notes:
775   A hyphen (-) must NOT be given at the beginning of the prefix name.
776   The first character of all runtime options is AUTOMATICALLY the hyphen.
777 
778   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
779   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
780 
781 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
782 @*/
783 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
784 {
785   PetscFunctionBegin;
786   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
787   if (prefix) {
788     PetscAssertPointer(prefix, 2);
789     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
790     if (prefix != A->factorprefix) {
791       PetscCall(PetscFree(A->factorprefix));
792       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
793     }
794   } else PetscCall(PetscFree(A->factorprefix));
795   PetscFunctionReturn(PETSC_SUCCESS);
796 }
797 
798 /*@
799   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
800   for matrices created with `MatGetFactor()`
801 
802   Logically Collective
803 
804   Input Parameters:
805 + A      - the matrix
806 - prefix - the prefix to prepend to all option names for the factored matrix
807 
808   Level: developer
809 
810   Notes:
811   A hyphen (-) must NOT be given at the beginning of the prefix name.
812   The first character of all runtime options is AUTOMATICALLY the hyphen.
813 
814   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
815   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
816 
817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
818           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
819           `MatSetOptionsPrefix()`
820 @*/
821 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
822 {
823   size_t len1, len2, new_len;
824 
825   PetscFunctionBegin;
826   PetscValidHeader(A, 1);
827   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
828   if (!A->factorprefix) {
829     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
830     PetscFunctionReturn(PETSC_SUCCESS);
831   }
832   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
833 
834   PetscCall(PetscStrlen(A->factorprefix, &len1));
835   PetscCall(PetscStrlen(prefix, &len2));
836   new_len = len1 + len2 + 1;
837   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
838   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
839   PetscFunctionReturn(PETSC_SUCCESS);
840 }
841 
842 /*@
843   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
844   matrix options in the database.
845 
846   Logically Collective
847 
848   Input Parameters:
849 + A      - the matrix
850 - prefix - the prefix to prepend to all option names
851 
852   Level: advanced
853 
854   Note:
855   A hyphen (-) must NOT be given at the beginning of the prefix name.
856   The first character of all runtime options is AUTOMATICALLY the hyphen.
857 
858 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
859 @*/
860 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
861 {
862   PetscFunctionBegin;
863   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
864   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
865   PetscTryMethod(A, "MatAppendOptionsPrefix_C", (Mat, const char[]), (A, prefix));
866   PetscFunctionReturn(PETSC_SUCCESS);
867 }
868 
869 /*@
870   MatGetOptionsPrefix - Gets the prefix used for searching for all
871   matrix options in the database.
872 
873   Not Collective
874 
875   Input Parameter:
876 . A - the matrix
877 
878   Output Parameter:
879 . prefix - pointer to the prefix string used
880 
881   Level: advanced
882 
883 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
884 @*/
885 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
886 {
887   PetscFunctionBegin;
888   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
889   PetscAssertPointer(prefix, 2);
890   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
891   PetscFunctionReturn(PETSC_SUCCESS);
892 }
893 
894 /*@
895   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
896 
897   Not Collective
898 
899   Input Parameter:
900 . A - the matrix
901 
902   Output Parameter:
903 . state - the object state
904 
905   Level: advanced
906 
907   Note:
908   Object state is an integer which gets increased every time
909   the object is changed. By saving and later querying the object state
910   one can determine whether information about the object is still current.
911 
912   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
913 
914 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
915 @*/
916 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
917 {
918   PetscFunctionBegin;
919   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
920   PetscAssertPointer(state, 2);
921   PetscCall(PetscObjectStateGet((PetscObject)A, state));
922   PetscFunctionReturn(PETSC_SUCCESS);
923 }
924 
925 /*@
926   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
927 
928   Collective
929 
930   Input Parameter:
931 . A - the matrix
932 
933   Level: beginner
934 
935   Notes:
936   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
937   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
938   makes all of the preallocation space available
939 
940   Current values in the matrix are lost in this call
941 
942   Currently only supported for  `MATAIJ` matrices.
943 
944 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
945 @*/
946 PetscErrorCode MatResetPreallocation(Mat A)
947 {
948   PetscFunctionBegin;
949   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
950   PetscValidType(A, 1);
951   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
952   PetscFunctionReturn(PETSC_SUCCESS);
953 }
954 
955 /*@
956   MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
957 
958   Collective
959 
960   Input Parameter:
961 . A - the matrix
962 
963   Level: intermediate
964 
965   Notes:
966   The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
967 
968   Currently only supported for `MATAIJ` matrices.
969 
970 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
971 @*/
972 PetscErrorCode MatResetHash(Mat A)
973 {
974   PetscFunctionBegin;
975   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
976   PetscValidType(A, 1);
977   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
978   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
979   PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
980   /* These flags are used to determine whether certain setups occur */
981   A->was_assembled = PETSC_FALSE;
982   A->assembled     = PETSC_FALSE;
983   /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
984   PetscCall(PetscObjectStateIncrease((PetscObject)A));
985   PetscFunctionReturn(PETSC_SUCCESS);
986 }
987 
988 /*@
989   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
990 
991   Collective
992 
993   Input Parameter:
994 . A - the matrix
995 
996   Level: advanced
997 
998   Notes:
999   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
1000   setting values in the matrix.
1001 
1002   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
1003 
1004 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
1005 @*/
1006 PetscErrorCode MatSetUp(Mat A)
1007 {
1008   PetscFunctionBegin;
1009   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1010   if (!((PetscObject)A)->type_name) {
1011     PetscMPIInt size;
1012 
1013     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1014     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
1015   }
1016   if (!A->preallocated) PetscTryTypeMethod(A, setup);
1017   PetscCall(PetscLayoutSetUp(A->rmap));
1018   PetscCall(PetscLayoutSetUp(A->cmap));
1019   A->preallocated = PETSC_TRUE;
1020   PetscFunctionReturn(PETSC_SUCCESS);
1021 }
1022 
1023 #if defined(PETSC_HAVE_SAWS)
1024   #include <petscviewersaws.h>
1025 #endif
1026 
1027 /*
1028    If threadsafety is on extraneous matrices may be printed
1029 
1030    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1031 */
1032 #if !defined(PETSC_HAVE_THREADSAFETY)
1033 static PetscInt insidematview = 0;
1034 #endif
1035 
1036 /*@
1037   MatViewFromOptions - View properties of the matrix based on options set in the options database
1038 
1039   Collective
1040 
1041   Input Parameters:
1042 + A    - the matrix
1043 . obj  - optional additional object that provides the options prefix to use
1044 - name - command line option
1045 
1046   Options Database Key:
1047 . -mat_view [viewertype]:... - the viewer and its options
1048 
1049   Level: intermediate
1050 
1051   Note:
1052 .vb
1053     If no value is provided ascii:stdout is used
1054        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1055                                                   for example ascii::ascii_info prints just the information about the object not all details
1056                                                   unless :append is given filename opens in write mode, overwriting what was already there
1057        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1058        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1059        socket[:port]                             defaults to the standard output port
1060        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1061 .ve
1062 
1063 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1064 @*/
1065 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1066 {
1067   PetscFunctionBegin;
1068   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1069 #if !defined(PETSC_HAVE_THREADSAFETY)
1070   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1071 #endif
1072   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1073   PetscFunctionReturn(PETSC_SUCCESS);
1074 }
1075 
1076 /*@
1077   MatView - display information about a matrix in a variety ways
1078 
1079   Collective on viewer
1080 
1081   Input Parameters:
1082 + mat    - the matrix
1083 - viewer - visualization context
1084 
1085   Options Database Keys:
1086 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1087 . -mat_view ::ascii_info_detail    - Prints more detailed info
1088 . -mat_view                        - Prints matrix in ASCII format
1089 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1090 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1091 . -display <name>                  - Sets display name (default is host)
1092 . -draw_pause <sec>                - Sets number of seconds to pause after display
1093 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1094 . -viewer_socket_machine <machine> - -
1095 . -viewer_socket_port <port>       - -
1096 . -mat_view binary                 - save matrix to file in binary format
1097 - -viewer_binary_filename <name>   - -
1098 
1099   Level: beginner
1100 
1101   Notes:
1102   The available visualization contexts include
1103 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1104 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1105 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1106 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1107 
1108   The user can open alternative visualization contexts with
1109 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1110 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1111 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1112 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1113 
1114   The user can call `PetscViewerPushFormat()` to specify the output
1115   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1116   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1117 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1118 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1119 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1120 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1121 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1122 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1123 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1124 
1125   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1126   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1127 
1128   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1129 
1130   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1131   viewer is used.
1132 
1133   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1134   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1135 
1136   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1137   and then use the following mouse functions.
1138 .vb
1139   left mouse: zoom in
1140   middle mouse: zoom out
1141   right mouse: continue with the simulation
1142 .ve
1143 
1144 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1145           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1146 @*/
1147 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1148 {
1149   PetscInt          rows, cols, rbs, cbs;
1150   PetscBool         isascii, isstring, issaws;
1151   PetscViewerFormat format;
1152   PetscMPIInt       size;
1153 
1154   PetscFunctionBegin;
1155   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1156   PetscValidType(mat, 1);
1157   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1158   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1159 
1160   PetscCall(PetscViewerGetFormat(viewer, &format));
1161   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1162   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1163 
1164 #if !defined(PETSC_HAVE_THREADSAFETY)
1165   insidematview++;
1166 #endif
1167   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1168   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1169   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1170   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");
1171 
1172   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1173   if (isascii) {
1174     if (!mat->preallocated) {
1175       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1176 #if !defined(PETSC_HAVE_THREADSAFETY)
1177       insidematview--;
1178 #endif
1179       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1180       PetscFunctionReturn(PETSC_SUCCESS);
1181     }
1182     if (!mat->assembled) {
1183       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1184 #if !defined(PETSC_HAVE_THREADSAFETY)
1185       insidematview--;
1186 #endif
1187       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1188       PetscFunctionReturn(PETSC_SUCCESS);
1189     }
1190     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1191     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1192       MatNullSpace nullsp, transnullsp;
1193 
1194       PetscCall(PetscViewerASCIIPushTab(viewer));
1195       PetscCall(MatGetSize(mat, &rows, &cols));
1196       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1197       if (rbs != 1 || cbs != 1) {
1198         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" : ""));
1199         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1200       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1201       if (mat->factortype) {
1202         MatSolverType solver;
1203         PetscCall(MatFactorGetSolverType(mat, &solver));
1204         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1205       }
1206       if (mat->ops->getinfo) {
1207         PetscBool is_constant_or_diagonal;
1208 
1209         // Don't print nonzero information for constant or diagonal matrices, it just adds noise to the output
1210         PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &is_constant_or_diagonal, MATCONSTANTDIAGONAL, MATDIAGONAL, ""));
1211         if (!is_constant_or_diagonal) {
1212           MatInfo info;
1213 
1214           PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1215           PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1216           if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1217         }
1218       }
1219       PetscCall(MatGetNullSpace(mat, &nullsp));
1220       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1221       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1222       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1223       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1224       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1225       PetscCall(PetscViewerASCIIPushTab(viewer));
1226       PetscCall(MatProductView(mat, viewer));
1227       PetscCall(PetscViewerASCIIPopTab(viewer));
1228       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1229         IS tmp;
1230 
1231         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1232         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1233         PetscCall(PetscViewerASCIIPushTab(viewer));
1234         PetscCall(ISView(tmp, viewer));
1235         PetscCall(PetscViewerASCIIPopTab(viewer));
1236         PetscCall(ISDestroy(&tmp));
1237       }
1238     }
1239   } else if (issaws) {
1240 #if defined(PETSC_HAVE_SAWS)
1241     PetscMPIInt rank;
1242 
1243     PetscCall(PetscObjectName((PetscObject)mat));
1244     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1245     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1246 #endif
1247   } else if (isstring) {
1248     const char *type;
1249     PetscCall(MatGetType(mat, &type));
1250     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1251     PetscTryTypeMethod(mat, view, viewer);
1252   }
1253   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1254     PetscCall(PetscViewerASCIIPushTab(viewer));
1255     PetscUseTypeMethod(mat, viewnative, viewer);
1256     PetscCall(PetscViewerASCIIPopTab(viewer));
1257   } else if (mat->ops->view) {
1258     PetscCall(PetscViewerASCIIPushTab(viewer));
1259     PetscUseTypeMethod(mat, view, viewer);
1260     PetscCall(PetscViewerASCIIPopTab(viewer));
1261   }
1262   if (isascii) {
1263     PetscCall(PetscViewerGetFormat(viewer, &format));
1264     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1265   }
1266   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1267 #if !defined(PETSC_HAVE_THREADSAFETY)
1268   insidematview--;
1269 #endif
1270   PetscFunctionReturn(PETSC_SUCCESS);
1271 }
1272 
1273 #if defined(PETSC_USE_DEBUG)
1274   #include <../src/sys/totalview/tv_data_display.h>
1275 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1276 {
1277   TV_add_row("Local rows", "int", &mat->rmap->n);
1278   TV_add_row("Local columns", "int", &mat->cmap->n);
1279   TV_add_row("Global rows", "int", &mat->rmap->N);
1280   TV_add_row("Global columns", "int", &mat->cmap->N);
1281   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1282   return TV_format_OK;
1283 }
1284 #endif
1285 
1286 /*@
1287   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1288   with `MatView()`.  The matrix format is determined from the options database.
1289   Generates a parallel MPI matrix if the communicator has more than one
1290   processor.  The default matrix type is `MATAIJ`.
1291 
1292   Collective
1293 
1294   Input Parameters:
1295 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1296             or some related function before a call to `MatLoad()`
1297 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1298 
1299   Options Database Key:
1300 . -matload_block_size <bs> - set block size
1301 
1302   Level: beginner
1303 
1304   Notes:
1305   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1306   `Mat` before calling this routine if you wish to set it from the options database.
1307 
1308   `MatLoad()` automatically loads into the options database any options
1309   given in the file filename.info where filename is the name of the file
1310   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1311   file will be ignored if you use the -viewer_binary_skip_info option.
1312 
1313   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1314   sets the default matrix type AIJ and sets the local and global sizes.
1315   If type and/or size is already set, then the same are used.
1316 
1317   In parallel, each processor can load a subset of rows (or the
1318   entire matrix).  This routine is especially useful when a large
1319   matrix is stored on disk and only part of it is desired on each
1320   processor.  For example, a parallel solver may access only some of
1321   the rows from each processor.  The algorithm used here reads
1322   relatively small blocks of data rather than reading the entire
1323   matrix and then subsetting it.
1324 
1325   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1326   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1327   or the sequence like
1328 .vb
1329     `PetscViewer` v;
1330     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1331     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1332     `PetscViewerSetFromOptions`(v);
1333     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1334     `PetscViewerFileSetName`(v,"datafile");
1335 .ve
1336   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1337 $ -viewer_type {binary, hdf5}
1338 
1339   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1340   and src/mat/tutorials/ex10.c with the second approach.
1341 
1342   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1343   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1344   Multiple objects, both matrices and vectors, can be stored within the same file.
1345   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1346 
1347   Most users should not need to know the details of the binary storage
1348   format, since `MatLoad()` and `MatView()` completely hide these details.
1349   But for anyone who is interested, the standard binary matrix storage
1350   format is
1351 
1352 .vb
1353     PetscInt    MAT_FILE_CLASSID
1354     PetscInt    number of rows
1355     PetscInt    number of columns
1356     PetscInt    total number of nonzeros
1357     PetscInt    *number nonzeros in each row
1358     PetscInt    *column indices of all nonzeros (starting index is zero)
1359     PetscScalar *values of all nonzeros
1360 .ve
1361   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1362   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
1363   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1364 
1365   PETSc automatically does the byte swapping for
1366   machines that store the bytes reversed. Thus if you write your own binary
1367   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1368   and `PetscBinaryWrite()` to see how this may be done.
1369 
1370   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1371   Each processor's chunk is loaded independently by its owning MPI process.
1372   Multiple objects, both matrices and vectors, can be stored within the same file.
1373   They are looked up by their PetscObject name.
1374 
1375   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1376   by default the same structure and naming of the AIJ arrays and column count
1377   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1378 $    save example.mat A b -v7.3
1379   can be directly read by this routine (see Reference 1 for details).
1380 
1381   Depending on your MATLAB version, this format might be a default,
1382   otherwise you can set it as default in Preferences.
1383 
1384   Unless -nocompression flag is used to save the file in MATLAB,
1385   PETSc must be configured with ZLIB package.
1386 
1387   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1388 
1389   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1390 
1391   Corresponding `MatView()` is not yet implemented.
1392 
1393   The loaded matrix is actually a transpose of the original one in MATLAB,
1394   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1395   With this format, matrix is automatically transposed by PETSc,
1396   unless the matrix is marked as SPD or symmetric
1397   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1398 
1399   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1400 
1401 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1402  @*/
1403 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1404 {
1405   PetscBool flg;
1406 
1407   PetscFunctionBegin;
1408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1409   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1410 
1411   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1412 
1413   flg = PETSC_FALSE;
1414   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1415   if (flg) {
1416     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1417     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1418   }
1419   flg = PETSC_FALSE;
1420   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1421   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1422 
1423   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1424   PetscUseTypeMethod(mat, load, viewer);
1425   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1426   PetscFunctionReturn(PETSC_SUCCESS);
1427 }
1428 
1429 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1430 {
1431   Mat_Redundant *redund = *redundant;
1432 
1433   PetscFunctionBegin;
1434   if (redund) {
1435     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1436       PetscCall(ISDestroy(&redund->isrow));
1437       PetscCall(ISDestroy(&redund->iscol));
1438       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1439     } else {
1440       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1441       PetscCall(PetscFree(redund->sbuf_j));
1442       PetscCall(PetscFree(redund->sbuf_a));
1443       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1444         PetscCall(PetscFree(redund->rbuf_j[i]));
1445         PetscCall(PetscFree(redund->rbuf_a[i]));
1446       }
1447       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1448     }
1449 
1450     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1451     PetscCall(PetscFree(redund));
1452   }
1453   PetscFunctionReturn(PETSC_SUCCESS);
1454 }
1455 
1456 /*@
1457   MatDestroy - Frees space taken by a matrix.
1458 
1459   Collective
1460 
1461   Input Parameter:
1462 . A - the matrix
1463 
1464   Level: beginner
1465 
1466   Developer Note:
1467   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1468   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1469   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1470   if changes are needed here.
1471 
1472 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1473 @*/
1474 PetscErrorCode MatDestroy(Mat *A)
1475 {
1476   PetscFunctionBegin;
1477   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1478   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1479   if (--((PetscObject)*A)->refct > 0) {
1480     *A = NULL;
1481     PetscFunctionReturn(PETSC_SUCCESS);
1482   }
1483 
1484   /* if memory was published with SAWs then destroy it */
1485   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1486   PetscTryTypeMethod(*A, destroy);
1487 
1488   PetscCall(PetscFree((*A)->factorprefix));
1489   PetscCall(PetscFree((*A)->defaultvectype));
1490   PetscCall(PetscFree((*A)->defaultrandtype));
1491   PetscCall(PetscFree((*A)->bsizes));
1492   PetscCall(PetscFree((*A)->solvertype));
1493   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1494   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1495   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1496   PetscCall(MatProductClear(*A));
1497   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1498   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1499   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1500   PetscCall(MatDestroy(&(*A)->schur));
1501   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1502   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1503   PetscCall(PetscHeaderDestroy(A));
1504   PetscFunctionReturn(PETSC_SUCCESS);
1505 }
1506 
1507 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1508 /*@
1509   MatSetValues - Inserts or adds a block of values into a matrix.
1510   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1511   MUST be called after all calls to `MatSetValues()` have been completed.
1512 
1513   Not Collective
1514 
1515   Input Parameters:
1516 + mat  - the matrix
1517 . v    - a logically two-dimensional array of values
1518 . m    - the number of rows
1519 . idxm - the global indices of the rows
1520 . n    - the number of columns
1521 . idxn - the global indices of the columns
1522 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1523 
1524   Level: beginner
1525 
1526   Notes:
1527   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1528 
1529   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1530   options cannot be mixed without intervening calls to the assembly
1531   routines.
1532 
1533   `MatSetValues()` uses 0-based row and column numbers in Fortran
1534   as well as in C.
1535 
1536   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1537   simply ignored. This allows easily inserting element stiffness matrices
1538   with homogeneous Dirichlet boundary conditions that you don't want represented
1539   in the matrix.
1540 
1541   Efficiency Alert:
1542   The routine `MatSetValuesBlocked()` may offer much better efficiency
1543   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1544 
1545   Fortran Notes:
1546   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1547 .vb
1548   call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
1549 .ve
1550 
1551   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1552 
1553   Developer Note:
1554   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1555   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1556 
1557 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1558           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1559 @*/
1560 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1561 {
1562   PetscFunctionBeginHot;
1563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1564   PetscValidType(mat, 1);
1565   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1566   PetscAssertPointer(idxm, 3);
1567   PetscAssertPointer(idxn, 5);
1568   MatCheckPreallocated(mat, 1);
1569 
1570   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1571   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1572 
1573   if (PetscDefined(USE_DEBUG)) {
1574     PetscInt i, j;
1575 
1576     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1577     if (v) {
1578       for (i = 0; i < m; i++) {
1579         for (j = 0; j < n; j++) {
1580           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1581 #if defined(PETSC_USE_COMPLEX)
1582             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]);
1583 #else
1584             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]);
1585 #endif
1586         }
1587       }
1588     }
1589     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);
1590     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);
1591   }
1592 
1593   if (mat->assembled) {
1594     mat->was_assembled = PETSC_TRUE;
1595     mat->assembled     = PETSC_FALSE;
1596   }
1597   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1598   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1599   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1600   PetscFunctionReturn(PETSC_SUCCESS);
1601 }
1602 
1603 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1604 /*@
1605   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1606   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1607   MUST be called after all calls to `MatSetValues()` have been completed.
1608 
1609   Not Collective
1610 
1611   Input Parameters:
1612 + mat  - the matrix
1613 . v    - a logically two-dimensional array of values
1614 . ism  - the rows to provide
1615 . isn  - the columns to provide
1616 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1617 
1618   Level: beginner
1619 
1620   Notes:
1621   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1622 
1623   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1624   options cannot be mixed without intervening calls to the assembly
1625   routines.
1626 
1627   `MatSetValues()` uses 0-based row and column numbers in Fortran
1628   as well as in C.
1629 
1630   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1631   simply ignored. This allows easily inserting element stiffness matrices
1632   with homogeneous Dirichlet boundary conditions that you don't want represented
1633   in the matrix.
1634 
1635   Efficiency Alert:
1636   The routine `MatSetValuesBlocked()` may offer much better efficiency
1637   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1638 
1639   This is currently not optimized for any particular `ISType`
1640 
1641   Developer Note:
1642   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1643   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1644 
1645 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1646           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1647 @*/
1648 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1649 {
1650   PetscInt        m, n;
1651   const PetscInt *rows, *cols;
1652 
1653   PetscFunctionBeginHot;
1654   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1655   PetscCall(ISGetIndices(ism, &rows));
1656   PetscCall(ISGetIndices(isn, &cols));
1657   PetscCall(ISGetLocalSize(ism, &m));
1658   PetscCall(ISGetLocalSize(isn, &n));
1659   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1660   PetscCall(ISRestoreIndices(ism, &rows));
1661   PetscCall(ISRestoreIndices(isn, &cols));
1662   PetscFunctionReturn(PETSC_SUCCESS);
1663 }
1664 
1665 /*@
1666   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1667   values into a matrix
1668 
1669   Not Collective
1670 
1671   Input Parameters:
1672 + mat - the matrix
1673 . row - the (block) row to set
1674 - v   - a logically two-dimensional array of values
1675 
1676   Level: intermediate
1677 
1678   Notes:
1679   The values, `v`, are column-oriented (for the block version) and sorted
1680 
1681   All the nonzero values in `row` must be provided
1682 
1683   The matrix must have previously had its column indices set, likely by having been assembled.
1684 
1685   `row` must belong to this MPI process
1686 
1687 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1688           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1689 @*/
1690 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1691 {
1692   PetscInt globalrow;
1693 
1694   PetscFunctionBegin;
1695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1696   PetscValidType(mat, 1);
1697   PetscAssertPointer(v, 3);
1698   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1699   PetscCall(MatSetValuesRow(mat, globalrow, v));
1700   PetscFunctionReturn(PETSC_SUCCESS);
1701 }
1702 
1703 /*@
1704   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1705   values into a matrix
1706 
1707   Not Collective
1708 
1709   Input Parameters:
1710 + mat - the matrix
1711 . row - the (block) row to set
1712 - 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
1713 
1714   Level: advanced
1715 
1716   Notes:
1717   The values, `v`, are column-oriented for the block version.
1718 
1719   All the nonzeros in `row` must be provided
1720 
1721   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1722 
1723   `row` must belong to this process
1724 
1725 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1726           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1727 @*/
1728 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1729 {
1730   PetscFunctionBeginHot;
1731   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1732   PetscValidType(mat, 1);
1733   MatCheckPreallocated(mat, 1);
1734   PetscAssertPointer(v, 3);
1735   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1736   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1737   mat->insertmode = INSERT_VALUES;
1738 
1739   if (mat->assembled) {
1740     mat->was_assembled = PETSC_TRUE;
1741     mat->assembled     = PETSC_FALSE;
1742   }
1743   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1744   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1745   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1746   PetscFunctionReturn(PETSC_SUCCESS);
1747 }
1748 
1749 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1750 /*@
1751   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1752   Using structured grid indexing
1753 
1754   Not Collective
1755 
1756   Input Parameters:
1757 + mat  - the matrix
1758 . m    - number of rows being entered
1759 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1760 . n    - number of columns being entered
1761 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1762 . v    - a logically two-dimensional array of values
1763 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1764 
1765   Level: beginner
1766 
1767   Notes:
1768   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1769 
1770   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1771   options cannot be mixed without intervening calls to the assembly
1772   routines.
1773 
1774   The grid coordinates are across the entire grid, not just the local portion
1775 
1776   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1777   as well as in C.
1778 
1779   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1780 
1781   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1782   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1783 
1784   The columns and rows in the stencil passed in MUST be contained within the
1785   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1786   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1787   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1788   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1789 
1790   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1791   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1792   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1793   `DM_BOUNDARY_PERIODIC` boundary type.
1794 
1795   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
1796   a single value per point) you can skip filling those indices.
1797 
1798   Inspired by the structured grid interface to the HYPRE package
1799   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1800 
1801   Efficiency Alert:
1802   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1803   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1804 
1805 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1806           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1807 @*/
1808 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1809 {
1810   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1811   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1812   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1813 
1814   PetscFunctionBegin;
1815   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1816   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1817   PetscValidType(mat, 1);
1818   PetscAssertPointer(idxm, 3);
1819   PetscAssertPointer(idxn, 5);
1820 
1821   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1822     jdxm = buf;
1823     jdxn = buf + m;
1824   } else {
1825     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1826     jdxm = bufm;
1827     jdxn = bufn;
1828   }
1829   for (i = 0; i < m; i++) {
1830     for (j = 0; j < 3 - sdim; j++) dxm++;
1831     tmp = *dxm++ - starts[0];
1832     for (j = 0; j < dim - 1; j++) {
1833       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1834       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1835     }
1836     if (mat->stencil.noc) dxm++;
1837     jdxm[i] = tmp;
1838   }
1839   for (i = 0; i < n; i++) {
1840     for (j = 0; j < 3 - sdim; j++) dxn++;
1841     tmp = *dxn++ - starts[0];
1842     for (j = 0; j < dim - 1; j++) {
1843       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1844       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1845     }
1846     if (mat->stencil.noc) dxn++;
1847     jdxn[i] = tmp;
1848   }
1849   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1850   PetscCall(PetscFree2(bufm, bufn));
1851   PetscFunctionReturn(PETSC_SUCCESS);
1852 }
1853 
1854 /*@
1855   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1856   Using structured grid indexing
1857 
1858   Not Collective
1859 
1860   Input Parameters:
1861 + mat  - the matrix
1862 . m    - number of rows being entered
1863 . idxm - grid coordinates for matrix rows being entered
1864 . n    - number of columns being entered
1865 . idxn - grid coordinates for matrix columns being entered
1866 . v    - a logically two-dimensional array of values
1867 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1868 
1869   Level: beginner
1870 
1871   Notes:
1872   By default the values, `v`, are row-oriented and unsorted.
1873   See `MatSetOption()` for other options.
1874 
1875   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1876   options cannot be mixed without intervening calls to the assembly
1877   routines.
1878 
1879   The grid coordinates are across the entire grid, not just the local portion
1880 
1881   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1882   as well as in C.
1883 
1884   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1885 
1886   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1887   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1888 
1889   The columns and rows in the stencil passed in MUST be contained within the
1890   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1891   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1892   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1893   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1894 
1895   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1896   simply ignored. This allows easily inserting element stiffness matrices
1897   with homogeneous Dirichlet boundary conditions that you don't want represented
1898   in the matrix.
1899 
1900   Inspired by the structured grid interface to the HYPRE package
1901   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1902 
1903   Fortran Note:
1904   `idxm` and `idxn` should be declared as
1905 .vb
1906     MatStencil idxm(4,m),idxn(4,n)
1907 .ve
1908   and the values inserted using
1909 .vb
1910     idxm(MatStencil_i,1) = i
1911     idxm(MatStencil_j,1) = j
1912     idxm(MatStencil_k,1) = k
1913    etc
1914 .ve
1915 
1916 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1917           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1918           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1919 @*/
1920 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1921 {
1922   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1923   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1924   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1925 
1926   PetscFunctionBegin;
1927   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1929   PetscValidType(mat, 1);
1930   PetscAssertPointer(idxm, 3);
1931   PetscAssertPointer(idxn, 5);
1932   PetscAssertPointer(v, 6);
1933 
1934   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1935     jdxm = buf;
1936     jdxn = buf + m;
1937   } else {
1938     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1939     jdxm = bufm;
1940     jdxn = bufn;
1941   }
1942   for (i = 0; i < m; i++) {
1943     for (j = 0; j < 3 - sdim; j++) dxm++;
1944     tmp = *dxm++ - starts[0];
1945     for (j = 0; j < sdim - 1; j++) {
1946       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1947       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1948     }
1949     dxm++;
1950     jdxm[i] = tmp;
1951   }
1952   for (i = 0; i < n; i++) {
1953     for (j = 0; j < 3 - sdim; j++) dxn++;
1954     tmp = *dxn++ - starts[0];
1955     for (j = 0; j < sdim - 1; j++) {
1956       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1957       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1958     }
1959     dxn++;
1960     jdxn[i] = tmp;
1961   }
1962   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1963   PetscCall(PetscFree2(bufm, bufn));
1964   PetscFunctionReturn(PETSC_SUCCESS);
1965 }
1966 
1967 /*@
1968   MatSetStencil - Sets the grid information for setting values into a matrix via
1969   `MatSetValuesStencil()`
1970 
1971   Not Collective
1972 
1973   Input Parameters:
1974 + mat    - the matrix
1975 . dim    - dimension of the grid 1, 2, or 3
1976 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1977 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1978 - dof    - number of degrees of freedom per node
1979 
1980   Level: beginner
1981 
1982   Notes:
1983   Inspired by the structured grid interface to the HYPRE package
1984   (www.llnl.gov/CASC/hyper)
1985 
1986   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1987   user.
1988 
1989 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1990           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1991 @*/
1992 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1993 {
1994   PetscFunctionBegin;
1995   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1996   PetscAssertPointer(dims, 3);
1997   PetscAssertPointer(starts, 4);
1998 
1999   mat->stencil.dim = dim + (dof > 1);
2000   for (PetscInt i = 0; i < dim; i++) {
2001     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
2002     mat->stencil.starts[i] = starts[dim - i - 1];
2003   }
2004   mat->stencil.dims[dim]   = dof;
2005   mat->stencil.starts[dim] = 0;
2006   mat->stencil.noc         = (PetscBool)(dof == 1);
2007   PetscFunctionReturn(PETSC_SUCCESS);
2008 }
2009 
2010 /*@
2011   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
2012 
2013   Not Collective
2014 
2015   Input Parameters:
2016 + mat  - the matrix
2017 . v    - a logically two-dimensional array of values
2018 . m    - the number of block rows
2019 . idxm - the global block indices
2020 . n    - the number of block columns
2021 . idxn - the global block indices
2022 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
2023 
2024   Level: intermediate
2025 
2026   Notes:
2027   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
2028   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
2029 
2030   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
2031   NOT the total number of rows/columns; for example, if the block size is 2 and
2032   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
2033   The values in `idxm` would be 1 2; that is the first index for each block divided by
2034   the block size.
2035 
2036   You must call `MatSetBlockSize()` when constructing this matrix (before
2037   preallocating it).
2038 
2039   By default the values, `v`, are row-oriented, so the layout of
2040   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
2041 
2042   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
2043   options cannot be mixed without intervening calls to the assembly
2044   routines.
2045 
2046   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2047   as well as in C.
2048 
2049   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2050   simply ignored. This allows easily inserting element stiffness matrices
2051   with homogeneous Dirichlet boundary conditions that you don't want represented
2052   in the matrix.
2053 
2054   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2055   internal searching must be done to determine where to place the
2056   data in the matrix storage space.  By instead inserting blocks of
2057   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2058   reduced.
2059 
2060   Example:
2061 .vb
2062    Suppose m=n=2 and block size(bs) = 2 The array is
2063 
2064    1  2  | 3  4
2065    5  6  | 7  8
2066    - - - | - - -
2067    9  10 | 11 12
2068    13 14 | 15 16
2069 
2070    v[] should be passed in like
2071    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2072 
2073   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2074    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2075 .ve
2076 
2077   Fortran Notes:
2078   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2079 .vb
2080   call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
2081 .ve
2082 
2083   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2084 
2085 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2086 @*/
2087 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2088 {
2089   PetscFunctionBeginHot;
2090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2091   PetscValidType(mat, 1);
2092   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2093   PetscAssertPointer(idxm, 3);
2094   PetscAssertPointer(idxn, 5);
2095   MatCheckPreallocated(mat, 1);
2096   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2097   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2098   if (PetscDefined(USE_DEBUG)) {
2099     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2100     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2101   }
2102   if (PetscDefined(USE_DEBUG)) {
2103     PetscInt rbs, cbs, M, N, i;
2104     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2105     PetscCall(MatGetSize(mat, &M, &N));
2106     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);
2107     for (i = 0; i < n; i++)
2108       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);
2109   }
2110   if (mat->assembled) {
2111     mat->was_assembled = PETSC_TRUE;
2112     mat->assembled     = PETSC_FALSE;
2113   }
2114   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2115   if (mat->ops->setvaluesblocked) {
2116     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2117   } else {
2118     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2119     PetscInt i, j, bs, cbs;
2120 
2121     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2122     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2123       iidxm = buf;
2124       iidxn = buf + m * bs;
2125     } else {
2126       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2127       iidxm = bufr;
2128       iidxn = bufc;
2129     }
2130     for (i = 0; i < m; i++) {
2131       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2132     }
2133     if (m != n || bs != cbs || idxm != idxn) {
2134       for (i = 0; i < n; i++) {
2135         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2136       }
2137     } else iidxn = iidxm;
2138     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2139     PetscCall(PetscFree2(bufr, bufc));
2140   }
2141   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2142   PetscFunctionReturn(PETSC_SUCCESS);
2143 }
2144 
2145 /*@
2146   MatGetValues - Gets a block of local values from a matrix.
2147 
2148   Not Collective; can only return values that are owned by the give process
2149 
2150   Input Parameters:
2151 + mat  - the matrix
2152 . v    - a logically two-dimensional array for storing the values
2153 . m    - the number of rows
2154 . idxm - the  global indices of the rows
2155 . n    - the number of columns
2156 - idxn - the global indices of the columns
2157 
2158   Level: advanced
2159 
2160   Notes:
2161   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2162   The values, `v`, are then returned in a row-oriented format,
2163   analogous to that used by default in `MatSetValues()`.
2164 
2165   `MatGetValues()` uses 0-based row and column numbers in
2166   Fortran as well as in C.
2167 
2168   `MatGetValues()` requires that the matrix has been assembled
2169   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2170   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2171   without intermediate matrix assembly.
2172 
2173   Negative row or column indices will be ignored and those locations in `v` will be
2174   left unchanged.
2175 
2176   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2177   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2178   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2179 
2180 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2181 @*/
2182 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2183 {
2184   PetscFunctionBegin;
2185   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2186   PetscValidType(mat, 1);
2187   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2188   PetscAssertPointer(idxm, 3);
2189   PetscAssertPointer(idxn, 5);
2190   PetscAssertPointer(v, 6);
2191   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2192   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2193   MatCheckPreallocated(mat, 1);
2194 
2195   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2196   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2197   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2198   PetscFunctionReturn(PETSC_SUCCESS);
2199 }
2200 
2201 /*@
2202   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2203   defined previously by `MatSetLocalToGlobalMapping()`
2204 
2205   Not Collective
2206 
2207   Input Parameters:
2208 + mat  - the matrix
2209 . nrow - number of rows
2210 . irow - the row local indices
2211 . ncol - number of columns
2212 - icol - the column local indices
2213 
2214   Output Parameter:
2215 . y - a logically two-dimensional array of values
2216 
2217   Level: advanced
2218 
2219   Notes:
2220   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2221 
2222   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,
2223   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2224   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2225   with `MatSetLocalToGlobalMapping()`.
2226 
2227   Developer Note:
2228   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2229   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2230 
2231 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2232           `MatSetValuesLocal()`, `MatGetValues()`
2233 @*/
2234 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2235 {
2236   PetscFunctionBeginHot;
2237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2238   PetscValidType(mat, 1);
2239   MatCheckPreallocated(mat, 1);
2240   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2241   PetscAssertPointer(irow, 3);
2242   PetscAssertPointer(icol, 5);
2243   if (PetscDefined(USE_DEBUG)) {
2244     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2245     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2246   }
2247   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2248   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2249   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2250   else {
2251     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2252     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2253       irowm = buf;
2254       icolm = buf + nrow;
2255     } else {
2256       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2257       irowm = bufr;
2258       icolm = bufc;
2259     }
2260     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2261     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2262     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2263     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2264     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2265     PetscCall(PetscFree2(bufr, bufc));
2266   }
2267   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2268   PetscFunctionReturn(PETSC_SUCCESS);
2269 }
2270 
2271 /*@
2272   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2273   the same size. Currently, this can only be called once and creates the given matrix.
2274 
2275   Not Collective
2276 
2277   Input Parameters:
2278 + mat  - the matrix
2279 . nb   - the number of blocks
2280 . bs   - the number of rows (and columns) in each block
2281 . rows - a concatenation of the rows for each block
2282 - v    - a concatenation of logically two-dimensional arrays of values
2283 
2284   Level: advanced
2285 
2286   Notes:
2287   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2288 
2289   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2290 
2291 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2292           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2293 @*/
2294 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2295 {
2296   PetscFunctionBegin;
2297   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2298   PetscValidType(mat, 1);
2299   PetscAssertPointer(rows, 4);
2300   PetscAssertPointer(v, 5);
2301   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2302 
2303   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2304   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2305   else {
2306     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2307   }
2308   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2309   PetscFunctionReturn(PETSC_SUCCESS);
2310 }
2311 
2312 /*@
2313   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2314   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2315   using a local (per-processor) numbering.
2316 
2317   Not Collective
2318 
2319   Input Parameters:
2320 + x        - the matrix
2321 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2322 - cmapping - column mapping
2323 
2324   Level: intermediate
2325 
2326   Note:
2327   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2328 
2329 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2330 @*/
2331 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2332 {
2333   PetscFunctionBegin;
2334   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2335   PetscValidType(x, 1);
2336   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2337   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2338   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2339   else {
2340     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2341     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2342   }
2343   PetscFunctionReturn(PETSC_SUCCESS);
2344 }
2345 
2346 /*@
2347   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2348 
2349   Not Collective
2350 
2351   Input Parameter:
2352 . A - the matrix
2353 
2354   Output Parameters:
2355 + rmapping - row mapping
2356 - cmapping - column mapping
2357 
2358   Level: advanced
2359 
2360 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2361 @*/
2362 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2363 {
2364   PetscFunctionBegin;
2365   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2366   PetscValidType(A, 1);
2367   if (rmapping) {
2368     PetscAssertPointer(rmapping, 2);
2369     *rmapping = A->rmap->mapping;
2370   }
2371   if (cmapping) {
2372     PetscAssertPointer(cmapping, 3);
2373     *cmapping = A->cmap->mapping;
2374   }
2375   PetscFunctionReturn(PETSC_SUCCESS);
2376 }
2377 
2378 /*@
2379   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2380 
2381   Logically Collective
2382 
2383   Input Parameters:
2384 + A    - the matrix
2385 . rmap - row layout
2386 - cmap - column layout
2387 
2388   Level: advanced
2389 
2390   Note:
2391   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2392 
2393 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2394 @*/
2395 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2396 {
2397   PetscFunctionBegin;
2398   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2399   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2400   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2401   PetscFunctionReturn(PETSC_SUCCESS);
2402 }
2403 
2404 /*@
2405   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2406 
2407   Not Collective
2408 
2409   Input Parameter:
2410 . A - the matrix
2411 
2412   Output Parameters:
2413 + rmap - row layout
2414 - cmap - column layout
2415 
2416   Level: advanced
2417 
2418 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2419 @*/
2420 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2421 {
2422   PetscFunctionBegin;
2423   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2424   PetscValidType(A, 1);
2425   if (rmap) {
2426     PetscAssertPointer(rmap, 2);
2427     *rmap = A->rmap;
2428   }
2429   if (cmap) {
2430     PetscAssertPointer(cmap, 3);
2431     *cmap = A->cmap;
2432   }
2433   PetscFunctionReturn(PETSC_SUCCESS);
2434 }
2435 
2436 /*@
2437   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2438   using a local numbering of the rows and columns.
2439 
2440   Not Collective
2441 
2442   Input Parameters:
2443 + mat  - the matrix
2444 . nrow - number of rows
2445 . irow - the row local indices
2446 . ncol - number of columns
2447 . icol - the column local indices
2448 . y    - a logically two-dimensional array of values
2449 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2450 
2451   Level: intermediate
2452 
2453   Notes:
2454   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2455 
2456   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2457   options cannot be mixed without intervening calls to the assembly
2458   routines.
2459 
2460   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2461   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2462 
2463   Fortran Notes:
2464   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2465 .vb
2466   call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2467 .ve
2468 
2469   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2470 
2471 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2472           `MatGetValuesLocal()`
2473 @*/
2474 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2475 {
2476   PetscFunctionBeginHot;
2477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2478   PetscValidType(mat, 1);
2479   MatCheckPreallocated(mat, 1);
2480   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2481   PetscAssertPointer(irow, 3);
2482   PetscAssertPointer(icol, 5);
2483   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2484   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2485   if (PetscDefined(USE_DEBUG)) {
2486     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2487     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2488   }
2489 
2490   if (mat->assembled) {
2491     mat->was_assembled = PETSC_TRUE;
2492     mat->assembled     = PETSC_FALSE;
2493   }
2494   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2495   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2496   else {
2497     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2498     const PetscInt *irowm, *icolm;
2499 
2500     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2501       bufr  = buf;
2502       bufc  = buf + nrow;
2503       irowm = bufr;
2504       icolm = bufc;
2505     } else {
2506       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2507       irowm = bufr;
2508       icolm = bufc;
2509     }
2510     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2511     else irowm = irow;
2512     if (mat->cmap->mapping) {
2513       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2514         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2515       } else icolm = irowm;
2516     } else icolm = icol;
2517     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2518     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2519   }
2520   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2521   PetscFunctionReturn(PETSC_SUCCESS);
2522 }
2523 
2524 /*@
2525   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2526   using a local ordering of the nodes a block at a time.
2527 
2528   Not Collective
2529 
2530   Input Parameters:
2531 + mat  - the matrix
2532 . nrow - number of rows
2533 . irow - the row local indices
2534 . ncol - number of columns
2535 . icol - the column local indices
2536 . y    - a logically two-dimensional array of values
2537 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2538 
2539   Level: intermediate
2540 
2541   Notes:
2542   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2543   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2544 
2545   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2546   options cannot be mixed without intervening calls to the assembly
2547   routines.
2548 
2549   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2550   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2551 
2552   Fortran Notes:
2553   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2554 .vb
2555   call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2556 .ve
2557 
2558   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2559 
2560 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2561           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2562 @*/
2563 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2564 {
2565   PetscFunctionBeginHot;
2566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2567   PetscValidType(mat, 1);
2568   MatCheckPreallocated(mat, 1);
2569   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2570   PetscAssertPointer(irow, 3);
2571   PetscAssertPointer(icol, 5);
2572   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2573   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2574   if (PetscDefined(USE_DEBUG)) {
2575     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2576     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);
2577   }
2578 
2579   if (mat->assembled) {
2580     mat->was_assembled = PETSC_TRUE;
2581     mat->assembled     = PETSC_FALSE;
2582   }
2583   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2584     PetscInt irbs, rbs;
2585     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2586     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2587     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2588   }
2589   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2590     PetscInt icbs, cbs;
2591     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2592     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2593     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2594   }
2595   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2596   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2597   else {
2598     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2599     const PetscInt *irowm, *icolm;
2600 
2601     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2602       bufr  = buf;
2603       bufc  = buf + nrow;
2604       irowm = bufr;
2605       icolm = bufc;
2606     } else {
2607       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2608       irowm = bufr;
2609       icolm = bufc;
2610     }
2611     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2612     else irowm = irow;
2613     if (mat->cmap->mapping) {
2614       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2615         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2616       } else icolm = irowm;
2617     } else icolm = icol;
2618     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2619     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2620   }
2621   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2622   PetscFunctionReturn(PETSC_SUCCESS);
2623 }
2624 
2625 /*@
2626   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2627 
2628   Collective
2629 
2630   Input Parameters:
2631 + mat - the matrix
2632 - x   - the vector to be multiplied
2633 
2634   Output Parameter:
2635 . y - the result
2636 
2637   Level: developer
2638 
2639   Note:
2640   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2641   call `MatMultDiagonalBlock`(A,y,y).
2642 
2643 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2644 @*/
2645 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2646 {
2647   PetscFunctionBegin;
2648   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2649   PetscValidType(mat, 1);
2650   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2651   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2652 
2653   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2654   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2655   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2656   MatCheckPreallocated(mat, 1);
2657 
2658   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2659   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2660   PetscFunctionReturn(PETSC_SUCCESS);
2661 }
2662 
2663 /*@
2664   MatMult - Computes the matrix-vector product, $y = Ax$.
2665 
2666   Neighbor-wise Collective
2667 
2668   Input Parameters:
2669 + mat - the matrix
2670 - x   - the vector to be multiplied
2671 
2672   Output Parameter:
2673 . y - the result
2674 
2675   Level: beginner
2676 
2677   Note:
2678   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2679   call `MatMult`(A,y,y).
2680 
2681 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2682 @*/
2683 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2684 {
2685   PetscFunctionBegin;
2686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2687   PetscValidType(mat, 1);
2688   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2689   VecCheckAssembled(x);
2690   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2691   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2692   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2693   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2694   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);
2695   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);
2696   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);
2697   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);
2698   PetscCall(VecSetErrorIfLocked(y, 3));
2699   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2700   MatCheckPreallocated(mat, 1);
2701 
2702   PetscCall(VecLockReadPush(x));
2703   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2704   PetscUseTypeMethod(mat, mult, x, y);
2705   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2706   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2707   PetscCall(VecLockReadPop(x));
2708   PetscFunctionReturn(PETSC_SUCCESS);
2709 }
2710 
2711 /*@
2712   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2713 
2714   Neighbor-wise Collective
2715 
2716   Input Parameters:
2717 + mat - the matrix
2718 - x   - the vector to be multiplied
2719 
2720   Output Parameter:
2721 . y - the result
2722 
2723   Level: beginner
2724 
2725   Notes:
2726   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2727   call `MatMultTranspose`(A,y,y).
2728 
2729   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2730   use `MatMultHermitianTranspose()`
2731 
2732 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2733 @*/
2734 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2735 {
2736   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2737 
2738   PetscFunctionBegin;
2739   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2740   PetscValidType(mat, 1);
2741   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2742   VecCheckAssembled(x);
2743   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2744 
2745   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2746   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2747   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2748   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);
2749   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);
2750   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);
2751   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);
2752   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2753   MatCheckPreallocated(mat, 1);
2754 
2755   if (!mat->ops->multtranspose) {
2756     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2757     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);
2758   } else op = mat->ops->multtranspose;
2759   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2760   PetscCall(VecLockReadPush(x));
2761   PetscCall((*op)(mat, x, y));
2762   PetscCall(VecLockReadPop(x));
2763   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2764   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2765   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2766   PetscFunctionReturn(PETSC_SUCCESS);
2767 }
2768 
2769 /*@
2770   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2771 
2772   Neighbor-wise Collective
2773 
2774   Input Parameters:
2775 + mat - the matrix
2776 - x   - the vector to be multiplied
2777 
2778   Output Parameter:
2779 . y - the result
2780 
2781   Level: beginner
2782 
2783   Notes:
2784   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2785   call `MatMultHermitianTranspose`(A,y,y).
2786 
2787   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2788 
2789   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2790 
2791 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2792 @*/
2793 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2794 {
2795   PetscFunctionBegin;
2796   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2797   PetscValidType(mat, 1);
2798   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2799   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2800 
2801   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2802   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2803   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2804   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);
2805   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);
2806   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);
2807   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);
2808   MatCheckPreallocated(mat, 1);
2809 
2810   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2811 #if defined(PETSC_USE_COMPLEX)
2812   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2813     PetscCall(VecLockReadPush(x));
2814     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2815     else PetscUseTypeMethod(mat, mult, x, y);
2816     PetscCall(VecLockReadPop(x));
2817   } else {
2818     Vec w;
2819     PetscCall(VecDuplicate(x, &w));
2820     PetscCall(VecCopy(x, w));
2821     PetscCall(VecConjugate(w));
2822     PetscCall(MatMultTranspose(mat, w, y));
2823     PetscCall(VecDestroy(&w));
2824     PetscCall(VecConjugate(y));
2825   }
2826   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2827 #else
2828   PetscCall(MatMultTranspose(mat, x, y));
2829 #endif
2830   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2831   PetscFunctionReturn(PETSC_SUCCESS);
2832 }
2833 
2834 /*@
2835   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2836 
2837   Neighbor-wise Collective
2838 
2839   Input Parameters:
2840 + mat - the matrix
2841 . v1  - the vector to be multiplied by `mat`
2842 - v2  - the vector to be added to the result
2843 
2844   Output Parameter:
2845 . v3 - the result
2846 
2847   Level: beginner
2848 
2849   Note:
2850   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2851   call `MatMultAdd`(A,v1,v2,v1).
2852 
2853 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2854 @*/
2855 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2856 {
2857   PetscFunctionBegin;
2858   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2859   PetscValidType(mat, 1);
2860   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2861   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2862   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2863 
2864   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2865   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2866   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);
2867   /* 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);
2868      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); */
2869   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);
2870   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);
2871   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2872   MatCheckPreallocated(mat, 1);
2873 
2874   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2875   PetscCall(VecLockReadPush(v1));
2876   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2877   PetscCall(VecLockReadPop(v1));
2878   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2879   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2880   PetscFunctionReturn(PETSC_SUCCESS);
2881 }
2882 
2883 /*@
2884   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2885 
2886   Neighbor-wise Collective
2887 
2888   Input Parameters:
2889 + mat - the matrix
2890 . v1  - the vector to be multiplied by the transpose of the matrix
2891 - v2  - the vector to be added to the result
2892 
2893   Output Parameter:
2894 . v3 - the result
2895 
2896   Level: beginner
2897 
2898   Note:
2899   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2900   call `MatMultTransposeAdd`(A,v1,v2,v1).
2901 
2902 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2903 @*/
2904 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2905 {
2906   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2907 
2908   PetscFunctionBegin;
2909   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2910   PetscValidType(mat, 1);
2911   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2912   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2913   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2914 
2915   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2916   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2917   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);
2918   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);
2919   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);
2920   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2921   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2922   MatCheckPreallocated(mat, 1);
2923 
2924   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2925   PetscCall(VecLockReadPush(v1));
2926   PetscCall((*op)(mat, v1, v2, v3));
2927   PetscCall(VecLockReadPop(v1));
2928   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2929   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2930   PetscFunctionReturn(PETSC_SUCCESS);
2931 }
2932 
2933 /*@
2934   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2935 
2936   Neighbor-wise Collective
2937 
2938   Input Parameters:
2939 + mat - the matrix
2940 . v1  - the vector to be multiplied by the Hermitian transpose
2941 - v2  - the vector to be added to the result
2942 
2943   Output Parameter:
2944 . v3 - the result
2945 
2946   Level: beginner
2947 
2948   Note:
2949   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2950   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2951 
2952 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2953 @*/
2954 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2955 {
2956   PetscFunctionBegin;
2957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2958   PetscValidType(mat, 1);
2959   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2960   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2961   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2962 
2963   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2964   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2965   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2966   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);
2967   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);
2968   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);
2969   MatCheckPreallocated(mat, 1);
2970 
2971   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2972   PetscCall(VecLockReadPush(v1));
2973   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2974   else {
2975     Vec w, z;
2976     PetscCall(VecDuplicate(v1, &w));
2977     PetscCall(VecCopy(v1, w));
2978     PetscCall(VecConjugate(w));
2979     PetscCall(VecDuplicate(v3, &z));
2980     PetscCall(MatMultTranspose(mat, w, z));
2981     PetscCall(VecDestroy(&w));
2982     PetscCall(VecConjugate(z));
2983     if (v2 != v3) {
2984       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2985     } else {
2986       PetscCall(VecAXPY(v3, 1.0, z));
2987     }
2988     PetscCall(VecDestroy(&z));
2989   }
2990   PetscCall(VecLockReadPop(v1));
2991   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2992   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2993   PetscFunctionReturn(PETSC_SUCCESS);
2994 }
2995 
2996 /*@
2997   MatGetFactorType - gets the type of factorization a matrix is
2998 
2999   Not Collective
3000 
3001   Input Parameter:
3002 . mat - the matrix
3003 
3004   Output Parameter:
3005 . 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`
3006 
3007   Level: intermediate
3008 
3009 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3010           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3011 @*/
3012 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
3013 {
3014   PetscFunctionBegin;
3015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3016   PetscValidType(mat, 1);
3017   PetscAssertPointer(t, 2);
3018   *t = mat->factortype;
3019   PetscFunctionReturn(PETSC_SUCCESS);
3020 }
3021 
3022 /*@
3023   MatSetFactorType - sets the type of factorization a matrix is
3024 
3025   Logically Collective
3026 
3027   Input Parameters:
3028 + mat - the matrix
3029 - 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`
3030 
3031   Level: intermediate
3032 
3033 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3034           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3035 @*/
3036 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3037 {
3038   PetscFunctionBegin;
3039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3040   PetscValidType(mat, 1);
3041   mat->factortype = t;
3042   PetscFunctionReturn(PETSC_SUCCESS);
3043 }
3044 
3045 /*@
3046   MatGetInfo - Returns information about matrix storage (number of
3047   nonzeros, memory, etc.).
3048 
3049   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3050 
3051   Input Parameters:
3052 + mat  - the matrix
3053 - 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)
3054 
3055   Output Parameter:
3056 . info - matrix information context
3057 
3058   Options Database Key:
3059 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3060 
3061   Level: intermediate
3062 
3063   Notes:
3064   The `MatInfo` context contains a variety of matrix data, including
3065   number of nonzeros allocated and used, number of mallocs during
3066   matrix assembly, etc.  Additional information for factored matrices
3067   is provided (such as the fill ratio, number of mallocs during
3068   factorization, etc.).
3069 
3070   Example:
3071   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3072   data within the `MatInfo` context.  For example,
3073 .vb
3074       MatInfo info;
3075       Mat     A;
3076       double  mal, nz_a, nz_u;
3077 
3078       MatGetInfo(A, MAT_LOCAL, &info);
3079       mal  = info.mallocs;
3080       nz_a = info.nz_allocated;
3081 .ve
3082 
3083 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3084 @*/
3085 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3086 {
3087   PetscFunctionBegin;
3088   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3089   PetscValidType(mat, 1);
3090   PetscAssertPointer(info, 3);
3091   MatCheckPreallocated(mat, 1);
3092   PetscUseTypeMethod(mat, getinfo, flag, info);
3093   PetscFunctionReturn(PETSC_SUCCESS);
3094 }
3095 
3096 /*
3097    This is used by external packages where it is not easy to get the info from the actual
3098    matrix factorization.
3099 */
3100 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3101 {
3102   PetscFunctionBegin;
3103   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3104   PetscFunctionReturn(PETSC_SUCCESS);
3105 }
3106 
3107 /*@
3108   MatLUFactor - Performs in-place LU factorization of matrix.
3109 
3110   Collective
3111 
3112   Input Parameters:
3113 + mat  - the matrix
3114 . row  - row permutation
3115 . col  - column permutation
3116 - info - options for factorization, includes
3117 .vb
3118           fill - expected fill as ratio of original fill.
3119           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3120                    Run with the option -info to determine an optimal value to use
3121 .ve
3122 
3123   Level: developer
3124 
3125   Notes:
3126   Most users should employ the `KSP` interface for linear solvers
3127   instead of working directly with matrix algebra routines such as this.
3128   See, e.g., `KSPCreate()`.
3129 
3130   This changes the state of the matrix to a factored matrix; it cannot be used
3131   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3132 
3133   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3134   when not using `KSP`.
3135 
3136   Developer Note:
3137   The Fortran interface is not autogenerated as the
3138   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3139 
3140 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3141           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3142 @*/
3143 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3144 {
3145   MatFactorInfo tinfo;
3146 
3147   PetscFunctionBegin;
3148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3149   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3150   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3151   if (info) PetscAssertPointer(info, 4);
3152   PetscValidType(mat, 1);
3153   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3154   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3155   MatCheckPreallocated(mat, 1);
3156   if (!info) {
3157     PetscCall(MatFactorInfoInitialize(&tinfo));
3158     info = &tinfo;
3159   }
3160 
3161   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3162   PetscUseTypeMethod(mat, lufactor, row, col, info);
3163   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3164   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3165   PetscFunctionReturn(PETSC_SUCCESS);
3166 }
3167 
3168 /*@
3169   MatILUFactor - Performs in-place ILU factorization of matrix.
3170 
3171   Collective
3172 
3173   Input Parameters:
3174 + mat  - the matrix
3175 . row  - row permutation
3176 . col  - column permutation
3177 - info - structure containing
3178 .vb
3179       levels - number of levels of fill.
3180       expected fill - as ratio of original fill.
3181       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3182                 missing diagonal entries)
3183 .ve
3184 
3185   Level: developer
3186 
3187   Notes:
3188   Most users should employ the `KSP` interface for linear solvers
3189   instead of working directly with matrix algebra routines such as this.
3190   See, e.g., `KSPCreate()`.
3191 
3192   Probably really in-place only when level of fill is zero, otherwise allocates
3193   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3194   when not using `KSP`.
3195 
3196   Developer Note:
3197   The Fortran interface is not autogenerated as the
3198   interface definition cannot be generated correctly [due to MatFactorInfo]
3199 
3200 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3201 @*/
3202 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3203 {
3204   PetscFunctionBegin;
3205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3206   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3207   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3208   PetscAssertPointer(info, 4);
3209   PetscValidType(mat, 1);
3210   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3211   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3212   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3213   MatCheckPreallocated(mat, 1);
3214 
3215   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3216   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3217   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3218   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3219   PetscFunctionReturn(PETSC_SUCCESS);
3220 }
3221 
3222 /*@
3223   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3224   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3225 
3226   Collective
3227 
3228   Input Parameters:
3229 + fact - the factor matrix obtained with `MatGetFactor()`
3230 . mat  - the matrix
3231 . row  - the row permutation
3232 . col  - the column permutation
3233 - info - options for factorization, includes
3234 .vb
3235           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3236           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3237 .ve
3238 
3239   Level: developer
3240 
3241   Notes:
3242   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3243 
3244   Most users should employ the simplified `KSP` interface for linear solvers
3245   instead of working directly with matrix algebra routines such as this.
3246   See, e.g., `KSPCreate()`.
3247 
3248   Developer Note:
3249   The Fortran interface is not autogenerated as the
3250   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3251 
3252 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3253 @*/
3254 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3255 {
3256   MatFactorInfo tinfo;
3257 
3258   PetscFunctionBegin;
3259   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3260   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3261   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3262   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3263   if (info) PetscAssertPointer(info, 5);
3264   PetscValidType(fact, 1);
3265   PetscValidType(mat, 2);
3266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3268   MatCheckPreallocated(mat, 2);
3269   if (!info) {
3270     PetscCall(MatFactorInfoInitialize(&tinfo));
3271     info = &tinfo;
3272   }
3273 
3274   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3275   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3276   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3277   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3278   PetscFunctionReturn(PETSC_SUCCESS);
3279 }
3280 
3281 /*@
3282   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3283   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3284 
3285   Collective
3286 
3287   Input Parameters:
3288 + fact - the factor matrix obtained with `MatGetFactor()`
3289 . mat  - the matrix
3290 - info - options for factorization
3291 
3292   Level: developer
3293 
3294   Notes:
3295   See `MatLUFactor()` for in-place factorization.  See
3296   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3297 
3298   Most users should employ the `KSP` interface for linear solvers
3299   instead of working directly with matrix algebra routines such as this.
3300   See, e.g., `KSPCreate()`.
3301 
3302   Developer Note:
3303   The Fortran interface is not autogenerated as the
3304   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3305 
3306 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3307 @*/
3308 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3309 {
3310   MatFactorInfo tinfo;
3311 
3312   PetscFunctionBegin;
3313   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3314   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3315   PetscValidType(fact, 1);
3316   PetscValidType(mat, 2);
3317   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3318   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,
3319              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3320 
3321   MatCheckPreallocated(mat, 2);
3322   if (!info) {
3323     PetscCall(MatFactorInfoInitialize(&tinfo));
3324     info = &tinfo;
3325   }
3326 
3327   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3328   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3329   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3330   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3331   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3332   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3333   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3334   PetscFunctionReturn(PETSC_SUCCESS);
3335 }
3336 
3337 /*@
3338   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3339   symmetric matrix.
3340 
3341   Collective
3342 
3343   Input Parameters:
3344 + mat  - the matrix
3345 . perm - row and column permutations
3346 - info - expected fill as ratio of original fill
3347 
3348   Level: developer
3349 
3350   Notes:
3351   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3352   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3353 
3354   Most users should employ the `KSP` interface for linear solvers
3355   instead of working directly with matrix algebra routines such as this.
3356   See, e.g., `KSPCreate()`.
3357 
3358   Developer Note:
3359   The Fortran interface is not autogenerated as the
3360   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3361 
3362 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3363           `MatGetOrdering()`
3364 @*/
3365 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3366 {
3367   MatFactorInfo tinfo;
3368 
3369   PetscFunctionBegin;
3370   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3371   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3372   if (info) PetscAssertPointer(info, 3);
3373   PetscValidType(mat, 1);
3374   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3375   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3376   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3377   MatCheckPreallocated(mat, 1);
3378   if (!info) {
3379     PetscCall(MatFactorInfoInitialize(&tinfo));
3380     info = &tinfo;
3381   }
3382 
3383   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3384   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3385   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3386   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3387   PetscFunctionReturn(PETSC_SUCCESS);
3388 }
3389 
3390 /*@
3391   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3392   of a symmetric matrix.
3393 
3394   Collective
3395 
3396   Input Parameters:
3397 + fact - the factor matrix obtained with `MatGetFactor()`
3398 . mat  - the matrix
3399 . perm - row and column permutations
3400 - info - options for factorization, includes
3401 .vb
3402           fill - expected fill as ratio of original fill.
3403           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3404                    Run with the option -info to determine an optimal value to use
3405 .ve
3406 
3407   Level: developer
3408 
3409   Notes:
3410   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3411   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3412 
3413   Most users should employ the `KSP` interface for linear solvers
3414   instead of working directly with matrix algebra routines such as this.
3415   See, e.g., `KSPCreate()`.
3416 
3417   Developer Note:
3418   The Fortran interface is not autogenerated as the
3419   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3420 
3421 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3422           `MatGetOrdering()`
3423 @*/
3424 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3425 {
3426   MatFactorInfo tinfo;
3427 
3428   PetscFunctionBegin;
3429   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3431   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3432   if (info) PetscAssertPointer(info, 4);
3433   PetscValidType(fact, 1);
3434   PetscValidType(mat, 2);
3435   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3436   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3437   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3438   MatCheckPreallocated(mat, 2);
3439   if (!info) {
3440     PetscCall(MatFactorInfoInitialize(&tinfo));
3441     info = &tinfo;
3442   }
3443 
3444   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3445   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3446   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3447   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3448   PetscFunctionReturn(PETSC_SUCCESS);
3449 }
3450 
3451 /*@
3452   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3453   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3454   `MatCholeskyFactorSymbolic()`.
3455 
3456   Collective
3457 
3458   Input Parameters:
3459 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3460 . mat  - the initial matrix that is to be factored
3461 - info - options for factorization
3462 
3463   Level: developer
3464 
3465   Note:
3466   Most users should employ the `KSP` interface for linear solvers
3467   instead of working directly with matrix algebra routines such as this.
3468   See, e.g., `KSPCreate()`.
3469 
3470   Developer Note:
3471   The Fortran interface is not autogenerated as the
3472   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3473 
3474 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3475 @*/
3476 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3477 {
3478   MatFactorInfo tinfo;
3479 
3480   PetscFunctionBegin;
3481   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3482   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3483   PetscValidType(fact, 1);
3484   PetscValidType(mat, 2);
3485   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3486   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,
3487              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3488   MatCheckPreallocated(mat, 2);
3489   if (!info) {
3490     PetscCall(MatFactorInfoInitialize(&tinfo));
3491     info = &tinfo;
3492   }
3493 
3494   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3495   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3496   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3497   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3498   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3499   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3500   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3501   PetscFunctionReturn(PETSC_SUCCESS);
3502 }
3503 
3504 /*@
3505   MatQRFactor - Performs in-place QR factorization of matrix.
3506 
3507   Collective
3508 
3509   Input Parameters:
3510 + mat  - the matrix
3511 . col  - column permutation
3512 - info - options for factorization, includes
3513 .vb
3514           fill - expected fill as ratio of original fill.
3515           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3516                    Run with the option -info to determine an optimal value to use
3517 .ve
3518 
3519   Level: developer
3520 
3521   Notes:
3522   Most users should employ the `KSP` interface for linear solvers
3523   instead of working directly with matrix algebra routines such as this.
3524   See, e.g., `KSPCreate()`.
3525 
3526   This changes the state of the matrix to a factored matrix; it cannot be used
3527   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3528 
3529   Developer Note:
3530   The Fortran interface is not autogenerated as the
3531   interface definition cannot be generated correctly [due to MatFactorInfo]
3532 
3533 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3534           `MatSetUnfactored()`
3535 @*/
3536 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3537 {
3538   PetscFunctionBegin;
3539   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3540   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3541   if (info) PetscAssertPointer(info, 3);
3542   PetscValidType(mat, 1);
3543   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3544   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3545   MatCheckPreallocated(mat, 1);
3546   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3547   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3548   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3549   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3550   PetscFunctionReturn(PETSC_SUCCESS);
3551 }
3552 
3553 /*@
3554   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3555   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3556 
3557   Collective
3558 
3559   Input Parameters:
3560 + fact - the factor matrix obtained with `MatGetFactor()`
3561 . mat  - the matrix
3562 . col  - column permutation
3563 - info - options for factorization, includes
3564 .vb
3565           fill - expected fill as ratio of original fill.
3566           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3567                    Run with the option -info to determine an optimal value to use
3568 .ve
3569 
3570   Level: developer
3571 
3572   Note:
3573   Most users should employ the `KSP` interface for linear solvers
3574   instead of working directly with matrix algebra routines such as this.
3575   See, e.g., `KSPCreate()`.
3576 
3577   Developer Note:
3578   The Fortran interface is not autogenerated as the
3579   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3580 
3581 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3582 @*/
3583 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3584 {
3585   MatFactorInfo tinfo;
3586 
3587   PetscFunctionBegin;
3588   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3589   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3590   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3591   if (info) PetscAssertPointer(info, 4);
3592   PetscValidType(fact, 1);
3593   PetscValidType(mat, 2);
3594   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3595   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3596   MatCheckPreallocated(mat, 2);
3597   if (!info) {
3598     PetscCall(MatFactorInfoInitialize(&tinfo));
3599     info = &tinfo;
3600   }
3601 
3602   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3603   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3604   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3605   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3606   PetscFunctionReturn(PETSC_SUCCESS);
3607 }
3608 
3609 /*@
3610   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3611   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3612 
3613   Collective
3614 
3615   Input Parameters:
3616 + fact - the factor matrix obtained with `MatGetFactor()`
3617 . mat  - the matrix
3618 - info - options for factorization
3619 
3620   Level: developer
3621 
3622   Notes:
3623   See `MatQRFactor()` for in-place factorization.
3624 
3625   Most users should employ the `KSP` interface for linear solvers
3626   instead of working directly with matrix algebra routines such as this.
3627   See, e.g., `KSPCreate()`.
3628 
3629   Developer Note:
3630   The Fortran interface is not autogenerated as the
3631   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3632 
3633 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3634 @*/
3635 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3636 {
3637   MatFactorInfo tinfo;
3638 
3639   PetscFunctionBegin;
3640   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3642   PetscValidType(fact, 1);
3643   PetscValidType(mat, 2);
3644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3645   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,
3646              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3647 
3648   MatCheckPreallocated(mat, 2);
3649   if (!info) {
3650     PetscCall(MatFactorInfoInitialize(&tinfo));
3651     info = &tinfo;
3652   }
3653 
3654   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3655   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3656   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3657   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3658   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3659   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3660   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3661   PetscFunctionReturn(PETSC_SUCCESS);
3662 }
3663 
3664 /*@
3665   MatSolve - Solves $A x = b$, given a factored matrix.
3666 
3667   Neighbor-wise Collective
3668 
3669   Input Parameters:
3670 + mat - the factored matrix
3671 - b   - the right-hand-side vector
3672 
3673   Output Parameter:
3674 . x - the result vector
3675 
3676   Level: developer
3677 
3678   Notes:
3679   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3680   call `MatSolve`(A,x,x).
3681 
3682   Most users should employ the `KSP` interface for linear solvers
3683   instead of working directly with matrix algebra routines such as this.
3684   See, e.g., `KSPCreate()`.
3685 
3686 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3687 @*/
3688 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3689 {
3690   PetscFunctionBegin;
3691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3692   PetscValidType(mat, 1);
3693   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3694   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3695   PetscCheckSameComm(mat, 1, b, 2);
3696   PetscCheckSameComm(mat, 1, x, 3);
3697   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3698   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);
3699   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);
3700   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);
3701   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3702   MatCheckPreallocated(mat, 1);
3703 
3704   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3705   PetscCall(VecFlag(x, mat->factorerrortype));
3706   if (mat->factorerrortype) {
3707     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3708   } else PetscUseTypeMethod(mat, solve, b, x);
3709   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3710   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3711   PetscFunctionReturn(PETSC_SUCCESS);
3712 }
3713 
3714 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3715 {
3716   Vec      b, x;
3717   PetscInt N, i;
3718   PetscErrorCode (*f)(Mat, Vec, Vec);
3719   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3720 
3721   PetscFunctionBegin;
3722   if (A->factorerrortype) {
3723     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3724     PetscCall(MatSetInf(X));
3725     PetscFunctionReturn(PETSC_SUCCESS);
3726   }
3727   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3728   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3729   PetscCall(MatBoundToCPU(A, &Abound));
3730   if (!Abound) {
3731     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3732     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3733   }
3734 #if PetscDefined(HAVE_CUDA)
3735   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3736   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3737 #elif PetscDefined(HAVE_HIP)
3738   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3739   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3740 #endif
3741   PetscCall(MatGetSize(B, NULL, &N));
3742   for (i = 0; i < N; i++) {
3743     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3744     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3745     PetscCall((*f)(A, b, x));
3746     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3747     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3748   }
3749   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3750   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3751   PetscFunctionReturn(PETSC_SUCCESS);
3752 }
3753 
3754 /*@
3755   MatMatSolve - Solves $A X = B$, given a factored matrix.
3756 
3757   Neighbor-wise Collective
3758 
3759   Input Parameters:
3760 + A - the factored matrix
3761 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3762 
3763   Output Parameter:
3764 . X - the result matrix (dense matrix)
3765 
3766   Level: developer
3767 
3768   Note:
3769   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3770   otherwise, `B` and `X` cannot be the same.
3771 
3772 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3773 @*/
3774 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3775 {
3776   PetscFunctionBegin;
3777   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3778   PetscValidType(A, 1);
3779   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3780   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3781   PetscCheckSameComm(A, 1, B, 2);
3782   PetscCheckSameComm(A, 1, X, 3);
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(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix");
3786   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3787   MatCheckPreallocated(A, 1);
3788 
3789   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3790   if (!A->ops->matsolve) {
3791     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3792     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3793   } else PetscUseTypeMethod(A, matsolve, B, X);
3794   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3795   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3796   PetscFunctionReturn(PETSC_SUCCESS);
3797 }
3798 
3799 /*@
3800   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3801 
3802   Neighbor-wise Collective
3803 
3804   Input Parameters:
3805 + A - the factored matrix
3806 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3807 
3808   Output Parameter:
3809 . X - the result matrix (dense matrix)
3810 
3811   Level: developer
3812 
3813   Note:
3814   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3815   call `MatMatSolveTranspose`(A,X,X).
3816 
3817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3818 @*/
3819 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3820 {
3821   PetscFunctionBegin;
3822   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3823   PetscValidType(A, 1);
3824   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3825   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3826   PetscCheckSameComm(A, 1, B, 2);
3827   PetscCheckSameComm(A, 1, X, 3);
3828   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3829   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);
3830   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);
3831   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);
3832   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");
3833   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3834   MatCheckPreallocated(A, 1);
3835 
3836   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3837   if (!A->ops->matsolvetranspose) {
3838     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3839     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3840   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3841   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3842   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3843   PetscFunctionReturn(PETSC_SUCCESS);
3844 }
3845 
3846 /*@
3847   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3848 
3849   Neighbor-wise Collective
3850 
3851   Input Parameters:
3852 + A  - the factored matrix
3853 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3854 
3855   Output Parameter:
3856 . X - the result matrix (dense matrix)
3857 
3858   Level: developer
3859 
3860   Note:
3861   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
3862   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3863 
3864 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3865 @*/
3866 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3867 {
3868   PetscFunctionBegin;
3869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3870   PetscValidType(A, 1);
3871   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3872   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3873   PetscCheckSameComm(A, 1, Bt, 2);
3874   PetscCheckSameComm(A, 1, X, 3);
3875 
3876   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3877   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);
3878   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);
3879   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");
3880   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3881   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3882   MatCheckPreallocated(A, 1);
3883 
3884   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3885   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3886   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3887   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3888   PetscFunctionReturn(PETSC_SUCCESS);
3889 }
3890 
3891 /*@
3892   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3893   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3894 
3895   Neighbor-wise Collective
3896 
3897   Input Parameters:
3898 + mat - the factored matrix
3899 - b   - the right-hand-side vector
3900 
3901   Output Parameter:
3902 . x - the result vector
3903 
3904   Level: developer
3905 
3906   Notes:
3907   `MatSolve()` should be used for most applications, as it performs
3908   a forward solve followed by a backward solve.
3909 
3910   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3911   call `MatForwardSolve`(A,x,x).
3912 
3913   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3914   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3915   `MatForwardSolve()` solves $U^T*D y = b$, and
3916   `MatBackwardSolve()` solves $U x = y$.
3917   Thus they do not provide a symmetric preconditioner.
3918 
3919 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3920 @*/
3921 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3922 {
3923   PetscFunctionBegin;
3924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3925   PetscValidType(mat, 1);
3926   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3927   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3928   PetscCheckSameComm(mat, 1, b, 2);
3929   PetscCheckSameComm(mat, 1, x, 3);
3930   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3931   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);
3932   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);
3933   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);
3934   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3935   MatCheckPreallocated(mat, 1);
3936 
3937   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3938   PetscUseTypeMethod(mat, forwardsolve, b, x);
3939   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3940   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3941   PetscFunctionReturn(PETSC_SUCCESS);
3942 }
3943 
3944 /*@
3945   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3946   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3947 
3948   Neighbor-wise Collective
3949 
3950   Input Parameters:
3951 + mat - the factored matrix
3952 - b   - the right-hand-side vector
3953 
3954   Output Parameter:
3955 . x - the result vector
3956 
3957   Level: developer
3958 
3959   Notes:
3960   `MatSolve()` should be used for most applications, as it performs
3961   a forward solve followed by a backward solve.
3962 
3963   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3964   call `MatBackwardSolve`(A,x,x).
3965 
3966   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3967   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3968   `MatForwardSolve()` solves $U^T*D y = b$, and
3969   `MatBackwardSolve()` solves $U x = y$.
3970   Thus they do not provide a symmetric preconditioner.
3971 
3972 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3973 @*/
3974 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3975 {
3976   PetscFunctionBegin;
3977   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3978   PetscValidType(mat, 1);
3979   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3980   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3981   PetscCheckSameComm(mat, 1, b, 2);
3982   PetscCheckSameComm(mat, 1, x, 3);
3983   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3984   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);
3985   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);
3986   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);
3987   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3988   MatCheckPreallocated(mat, 1);
3989 
3990   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3991   PetscUseTypeMethod(mat, backwardsolve, b, x);
3992   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3993   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3994   PetscFunctionReturn(PETSC_SUCCESS);
3995 }
3996 
3997 /*@
3998   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3999 
4000   Neighbor-wise Collective
4001 
4002   Input Parameters:
4003 + mat - the factored matrix
4004 . b   - the right-hand-side vector
4005 - y   - the vector to be added to
4006 
4007   Output Parameter:
4008 . x - the result vector
4009 
4010   Level: developer
4011 
4012   Note:
4013   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4014   call `MatSolveAdd`(A,x,y,x).
4015 
4016 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
4017 @*/
4018 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
4019 {
4020   PetscScalar one = 1.0;
4021   Vec         tmp;
4022 
4023   PetscFunctionBegin;
4024   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4025   PetscValidType(mat, 1);
4026   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4027   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4028   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4029   PetscCheckSameComm(mat, 1, b, 2);
4030   PetscCheckSameComm(mat, 1, y, 3);
4031   PetscCheckSameComm(mat, 1, x, 4);
4032   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4033   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);
4034   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);
4035   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);
4036   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);
4037   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);
4038   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4039   MatCheckPreallocated(mat, 1);
4040 
4041   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4042   PetscCall(VecFlag(x, mat->factorerrortype));
4043   if (mat->factorerrortype) {
4044     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4045   } else if (mat->ops->solveadd) {
4046     PetscUseTypeMethod(mat, solveadd, b, y, x);
4047   } else {
4048     /* do the solve then the add manually */
4049     if (x != y) {
4050       PetscCall(MatSolve(mat, b, x));
4051       PetscCall(VecAXPY(x, one, y));
4052     } else {
4053       PetscCall(VecDuplicate(x, &tmp));
4054       PetscCall(VecCopy(x, tmp));
4055       PetscCall(MatSolve(mat, b, x));
4056       PetscCall(VecAXPY(x, one, tmp));
4057       PetscCall(VecDestroy(&tmp));
4058     }
4059   }
4060   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4061   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4062   PetscFunctionReturn(PETSC_SUCCESS);
4063 }
4064 
4065 /*@
4066   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4067 
4068   Neighbor-wise Collective
4069 
4070   Input Parameters:
4071 + mat - the factored matrix
4072 - b   - the right-hand-side vector
4073 
4074   Output Parameter:
4075 . x - the result vector
4076 
4077   Level: developer
4078 
4079   Notes:
4080   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4081   call `MatSolveTranspose`(A,x,x).
4082 
4083   Most users should employ the `KSP` interface for linear solvers
4084   instead of working directly with matrix algebra routines such as this.
4085   See, e.g., `KSPCreate()`.
4086 
4087 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4088 @*/
4089 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4090 {
4091   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4092 
4093   PetscFunctionBegin;
4094   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4095   PetscValidType(mat, 1);
4096   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4097   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4098   PetscCheckSameComm(mat, 1, b, 2);
4099   PetscCheckSameComm(mat, 1, x, 3);
4100   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4101   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);
4102   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);
4103   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4104   MatCheckPreallocated(mat, 1);
4105   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4106   PetscCall(VecFlag(x, mat->factorerrortype));
4107   if (mat->factorerrortype) {
4108     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4109   } else {
4110     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4111     PetscCall((*f)(mat, b, x));
4112   }
4113   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4114   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4115   PetscFunctionReturn(PETSC_SUCCESS);
4116 }
4117 
4118 /*@
4119   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4120   factored matrix.
4121 
4122   Neighbor-wise Collective
4123 
4124   Input Parameters:
4125 + mat - the factored matrix
4126 . b   - the right-hand-side vector
4127 - y   - the vector to be added to
4128 
4129   Output Parameter:
4130 . x - the result vector
4131 
4132   Level: developer
4133 
4134   Note:
4135   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4136   call `MatSolveTransposeAdd`(A,x,y,x).
4137 
4138 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4139 @*/
4140 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4141 {
4142   PetscScalar one = 1.0;
4143   Vec         tmp;
4144   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4145 
4146   PetscFunctionBegin;
4147   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4148   PetscValidType(mat, 1);
4149   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4150   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4151   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4152   PetscCheckSameComm(mat, 1, b, 2);
4153   PetscCheckSameComm(mat, 1, y, 3);
4154   PetscCheckSameComm(mat, 1, x, 4);
4155   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4156   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);
4157   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);
4158   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);
4159   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);
4160   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4161   MatCheckPreallocated(mat, 1);
4162 
4163   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4164   PetscCall(VecFlag(x, mat->factorerrortype));
4165   if (mat->factorerrortype) {
4166     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4167   } else if (f) {
4168     PetscCall((*f)(mat, b, y, x));
4169   } else {
4170     /* do the solve then the add manually */
4171     if (x != y) {
4172       PetscCall(MatSolveTranspose(mat, b, x));
4173       PetscCall(VecAXPY(x, one, y));
4174     } else {
4175       PetscCall(VecDuplicate(x, &tmp));
4176       PetscCall(VecCopy(x, tmp));
4177       PetscCall(MatSolveTranspose(mat, b, x));
4178       PetscCall(VecAXPY(x, one, tmp));
4179       PetscCall(VecDestroy(&tmp));
4180     }
4181   }
4182   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4183   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4184   PetscFunctionReturn(PETSC_SUCCESS);
4185 }
4186 
4187 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4188 /*@
4189   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4190 
4191   Neighbor-wise Collective
4192 
4193   Input Parameters:
4194 + mat   - the matrix
4195 . b     - the right-hand side
4196 . omega - the relaxation factor
4197 . flag  - flag indicating the type of SOR (see below)
4198 . shift - diagonal shift
4199 . its   - the number of iterations
4200 - lits  - the number of local iterations
4201 
4202   Output Parameter:
4203 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4204 
4205   SOR Flags:
4206 +     `SOR_FORWARD_SWEEP` - forward SOR
4207 .     `SOR_BACKWARD_SWEEP` - backward SOR
4208 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4209 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4210 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4211 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4212 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4213 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4214   upper/lower triangular part of matrix to
4215   vector (with omega)
4216 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4217 
4218   Level: developer
4219 
4220   Notes:
4221   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4222   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4223   on each processor.
4224 
4225   Application programmers will not generally use `MatSOR()` directly,
4226   but instead will employ the `KSP`/`PC` interface.
4227 
4228   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4229 
4230   Most users should employ the `KSP` interface for linear solvers
4231   instead of working directly with matrix algebra routines such as this.
4232   See, e.g., `KSPCreate()`.
4233 
4234   Vectors `x` and `b` CANNOT be the same
4235 
4236   The flags are implemented as bitwise inclusive or operations.
4237   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4238   to specify a zero initial guess for SSOR.
4239 
4240   Developer Note:
4241   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4242 
4243 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4244 @*/
4245 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4246 {
4247   PetscFunctionBegin;
4248   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4249   PetscValidType(mat, 1);
4250   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4251   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4252   PetscCheckSameComm(mat, 1, b, 2);
4253   PetscCheckSameComm(mat, 1, x, 8);
4254   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4255   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4256   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);
4257   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);
4258   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);
4259   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4260   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4261   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4262 
4263   MatCheckPreallocated(mat, 1);
4264   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4265   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4266   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4267   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4268   PetscFunctionReturn(PETSC_SUCCESS);
4269 }
4270 
4271 /*
4272       Default matrix copy routine.
4273 */
4274 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4275 {
4276   PetscInt           i, rstart = 0, rend = 0, nz;
4277   const PetscInt    *cwork;
4278   const PetscScalar *vwork;
4279 
4280   PetscFunctionBegin;
4281   if (B->assembled) PetscCall(MatZeroEntries(B));
4282   if (str == SAME_NONZERO_PATTERN) {
4283     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4284     for (i = rstart; i < rend; i++) {
4285       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4286       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4287       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4288     }
4289   } else {
4290     PetscCall(MatAYPX(B, 0.0, A, str));
4291   }
4292   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4293   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4294   PetscFunctionReturn(PETSC_SUCCESS);
4295 }
4296 
4297 /*@
4298   MatCopy - Copies a matrix to another matrix.
4299 
4300   Collective
4301 
4302   Input Parameters:
4303 + A   - the matrix
4304 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4305 
4306   Output Parameter:
4307 . B - where the copy is put
4308 
4309   Level: intermediate
4310 
4311   Notes:
4312   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4313 
4314   `MatCopy()` copies the matrix entries of a matrix to another existing
4315   matrix (after first zeroing the second matrix).  A related routine is
4316   `MatConvert()`, which first creates a new matrix and then copies the data.
4317 
4318 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4319 @*/
4320 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4321 {
4322   PetscInt i;
4323 
4324   PetscFunctionBegin;
4325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4326   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4327   PetscValidType(A, 1);
4328   PetscValidType(B, 2);
4329   PetscCheckSameComm(A, 1, B, 2);
4330   MatCheckPreallocated(B, 2);
4331   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4332   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4333   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,
4334              A->cmap->N, B->cmap->N);
4335   MatCheckPreallocated(A, 1);
4336   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4337 
4338   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4339   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4340   else PetscCall(MatCopy_Basic(A, B, str));
4341 
4342   B->stencil.dim = A->stencil.dim;
4343   B->stencil.noc = A->stencil.noc;
4344   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4345     B->stencil.dims[i]   = A->stencil.dims[i];
4346     B->stencil.starts[i] = A->stencil.starts[i];
4347   }
4348 
4349   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4350   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4351   PetscFunctionReturn(PETSC_SUCCESS);
4352 }
4353 
4354 /*@
4355   MatConvert - Converts a matrix to another matrix, either of the same
4356   or different type.
4357 
4358   Collective
4359 
4360   Input Parameters:
4361 + mat     - the matrix
4362 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4363             same type as the original matrix.
4364 - reuse   - denotes if the destination matrix is to be created or reused.
4365             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
4366             `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).
4367 
4368   Output Parameter:
4369 . M - pointer to place new matrix
4370 
4371   Level: intermediate
4372 
4373   Notes:
4374   `MatConvert()` first creates a new matrix and then copies the data from
4375   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4376   entries of one matrix to another already existing matrix context.
4377 
4378   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4379   the MPI communicator of the generated matrix is always the same as the communicator
4380   of the input matrix.
4381 
4382 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4383 @*/
4384 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4385 {
4386   PetscBool  sametype, issame, flg;
4387   PetscBool3 issymmetric, ishermitian;
4388   char       convname[256], mtype[256];
4389   Mat        B;
4390 
4391   PetscFunctionBegin;
4392   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4393   PetscValidType(mat, 1);
4394   PetscAssertPointer(M, 4);
4395   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4396   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4397   MatCheckPreallocated(mat, 1);
4398 
4399   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4400   if (flg) newtype = mtype;
4401 
4402   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4403   PetscCall(PetscStrcmp(newtype, "same", &issame));
4404   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4405   if (reuse == MAT_REUSE_MATRIX) {
4406     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4407     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4408   }
4409 
4410   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4411     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4412     PetscFunctionReturn(PETSC_SUCCESS);
4413   }
4414 
4415   /* Cache Mat options because some converters use MatHeaderReplace  */
4416   issymmetric = mat->symmetric;
4417   ishermitian = mat->hermitian;
4418 
4419   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4420     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4421     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4422   } else {
4423     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4424     const char *prefix[3]                                 = {"seq", "mpi", ""};
4425     PetscInt    i;
4426     /*
4427        Order of precedence:
4428        0) See if newtype is a superclass of the current matrix.
4429        1) See if a specialized converter is known to the current matrix.
4430        2) See if a specialized converter is known to the desired matrix class.
4431        3) See if a good general converter is registered for the desired class
4432           (as of 6/27/03 only MATMPIADJ falls into this category).
4433        4) See if a good general converter is known for the current matrix.
4434        5) Use a really basic converter.
4435     */
4436 
4437     /* 0) See if newtype is a superclass of the current matrix.
4438           i.e mat is mpiaij and newtype is aij */
4439     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4440       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4441       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4442       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4443       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4444       if (flg) {
4445         if (reuse == MAT_INPLACE_MATRIX) {
4446           PetscCall(PetscInfo(mat, "Early return\n"));
4447           PetscFunctionReturn(PETSC_SUCCESS);
4448         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4449           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4450           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4451           PetscFunctionReturn(PETSC_SUCCESS);
4452         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4453           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4454           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4455           PetscFunctionReturn(PETSC_SUCCESS);
4456         }
4457       }
4458     }
4459     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4460     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4461       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4462       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4463       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4464       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4465       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4466       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4467       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4468       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4469       if (conv) goto foundconv;
4470     }
4471 
4472     /* 2)  See if a specialized converter is known to the desired matrix class. */
4473     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4474     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4475     PetscCall(MatSetType(B, newtype));
4476     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4477       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4478       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4479       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4480       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4481       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4482       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4483       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4484       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4485       if (conv) {
4486         PetscCall(MatDestroy(&B));
4487         goto foundconv;
4488       }
4489     }
4490 
4491     /* 3) See if a good general converter is registered for the desired class */
4492     conv = B->ops->convertfrom;
4493     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4494     PetscCall(MatDestroy(&B));
4495     if (conv) goto foundconv;
4496 
4497     /* 4) See if a good general converter is known for the current matrix */
4498     if (mat->ops->convert) conv = mat->ops->convert;
4499     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4500     if (conv) goto foundconv;
4501 
4502     /* 5) Use a really basic converter. */
4503     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4504     conv = MatConvert_Basic;
4505 
4506   foundconv:
4507     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4508     PetscCall((*conv)(mat, newtype, reuse, M));
4509     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4510       /* the block sizes must be same if the mappings are copied over */
4511       (*M)->rmap->bs = mat->rmap->bs;
4512       (*M)->cmap->bs = mat->cmap->bs;
4513       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4514       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4515       (*M)->rmap->mapping = mat->rmap->mapping;
4516       (*M)->cmap->mapping = mat->cmap->mapping;
4517     }
4518     (*M)->stencil.dim = mat->stencil.dim;
4519     (*M)->stencil.noc = mat->stencil.noc;
4520     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4521       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4522       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4523     }
4524     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4525   }
4526   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4527 
4528   /* Copy Mat options */
4529   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4530   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4531   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4532   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4533   PetscFunctionReturn(PETSC_SUCCESS);
4534 }
4535 
4536 /*@
4537   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4538 
4539   Not Collective
4540 
4541   Input Parameter:
4542 . mat - the matrix, must be a factored matrix
4543 
4544   Output Parameter:
4545 . type - the string name of the package (do not free this string)
4546 
4547   Level: intermediate
4548 
4549 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4550 @*/
4551 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4552 {
4553   PetscErrorCode (*conv)(Mat, MatSolverType *);
4554 
4555   PetscFunctionBegin;
4556   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4557   PetscValidType(mat, 1);
4558   PetscAssertPointer(type, 2);
4559   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4560   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4561   if (conv) PetscCall((*conv)(mat, type));
4562   else *type = MATSOLVERPETSC;
4563   PetscFunctionReturn(PETSC_SUCCESS);
4564 }
4565 
4566 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4567 struct _MatSolverTypeForSpecifcType {
4568   MatType mtype;
4569   /* no entry for MAT_FACTOR_NONE */
4570   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4571   MatSolverTypeForSpecifcType next;
4572 };
4573 
4574 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4575 struct _MatSolverTypeHolder {
4576   char                       *name;
4577   MatSolverTypeForSpecifcType handlers;
4578   MatSolverTypeHolder         next;
4579 };
4580 
4581 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4582 
4583 /*@C
4584   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4585 
4586   Logically Collective, No Fortran Support
4587 
4588   Input Parameters:
4589 + package      - name of the package, for example `petsc` or `superlu`
4590 . mtype        - the matrix type that works with this package
4591 . ftype        - the type of factorization supported by the package
4592 - createfactor - routine that will create the factored matrix ready to be used
4593 
4594   Level: developer
4595 
4596 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4597   `MatGetFactor()`
4598 @*/
4599 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4600 {
4601   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4602   PetscBool                   flg;
4603   MatSolverTypeForSpecifcType inext, iprev = NULL;
4604 
4605   PetscFunctionBegin;
4606   PetscCall(MatInitializePackage());
4607   if (!next) {
4608     PetscCall(PetscNew(&MatSolverTypeHolders));
4609     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4610     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4611     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4612     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4613     PetscFunctionReturn(PETSC_SUCCESS);
4614   }
4615   while (next) {
4616     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4617     if (flg) {
4618       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4619       inext = next->handlers;
4620       while (inext) {
4621         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4622         if (flg) {
4623           inext->createfactor[(int)ftype - 1] = createfactor;
4624           PetscFunctionReturn(PETSC_SUCCESS);
4625         }
4626         iprev = inext;
4627         inext = inext->next;
4628       }
4629       PetscCall(PetscNew(&iprev->next));
4630       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4631       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4632       PetscFunctionReturn(PETSC_SUCCESS);
4633     }
4634     prev = next;
4635     next = next->next;
4636   }
4637   PetscCall(PetscNew(&prev->next));
4638   PetscCall(PetscStrallocpy(package, &prev->next->name));
4639   PetscCall(PetscNew(&prev->next->handlers));
4640   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4641   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4642   PetscFunctionReturn(PETSC_SUCCESS);
4643 }
4644 
4645 /*@C
4646   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4647 
4648   Input Parameters:
4649 + 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
4650 . ftype - the type of factorization supported by the type
4651 - mtype - the matrix type that works with this type
4652 
4653   Output Parameters:
4654 + foundtype    - `PETSC_TRUE` if the type was registered
4655 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4656 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4657 
4658   Calling sequence of `createfactor`:
4659 + A     - the matrix providing the factor matrix
4660 . ftype - the `MatFactorType` of the factor requested
4661 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4662 
4663   Level: developer
4664 
4665   Note:
4666   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4667   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4668   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4669 
4670 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4671           `MatInitializePackage()`
4672 @*/
4673 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4674 {
4675   MatSolverTypeHolder         next = MatSolverTypeHolders;
4676   PetscBool                   flg;
4677   MatSolverTypeForSpecifcType inext;
4678 
4679   PetscFunctionBegin;
4680   if (foundtype) *foundtype = PETSC_FALSE;
4681   if (foundmtype) *foundmtype = PETSC_FALSE;
4682   if (createfactor) *createfactor = NULL;
4683 
4684   if (type) {
4685     while (next) {
4686       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4687       if (flg) {
4688         if (foundtype) *foundtype = PETSC_TRUE;
4689         inext = next->handlers;
4690         while (inext) {
4691           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4692           if (flg) {
4693             if (foundmtype) *foundmtype = PETSC_TRUE;
4694             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4695             PetscFunctionReturn(PETSC_SUCCESS);
4696           }
4697           inext = inext->next;
4698         }
4699       }
4700       next = next->next;
4701     }
4702   } else {
4703     while (next) {
4704       inext = next->handlers;
4705       while (inext) {
4706         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4707         if (flg && inext->createfactor[(int)ftype - 1]) {
4708           if (foundtype) *foundtype = PETSC_TRUE;
4709           if (foundmtype) *foundmtype = PETSC_TRUE;
4710           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4711           PetscFunctionReturn(PETSC_SUCCESS);
4712         }
4713         inext = inext->next;
4714       }
4715       next = next->next;
4716     }
4717     /* try with base classes inext->mtype */
4718     next = MatSolverTypeHolders;
4719     while (next) {
4720       inext = next->handlers;
4721       while (inext) {
4722         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4723         if (flg && inext->createfactor[(int)ftype - 1]) {
4724           if (foundtype) *foundtype = PETSC_TRUE;
4725           if (foundmtype) *foundmtype = PETSC_TRUE;
4726           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4727           PetscFunctionReturn(PETSC_SUCCESS);
4728         }
4729         inext = inext->next;
4730       }
4731       next = next->next;
4732     }
4733   }
4734   PetscFunctionReturn(PETSC_SUCCESS);
4735 }
4736 
4737 PetscErrorCode MatSolverTypeDestroy(void)
4738 {
4739   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4740   MatSolverTypeForSpecifcType inext, iprev;
4741 
4742   PetscFunctionBegin;
4743   while (next) {
4744     PetscCall(PetscFree(next->name));
4745     inext = next->handlers;
4746     while (inext) {
4747       PetscCall(PetscFree(inext->mtype));
4748       iprev = inext;
4749       inext = inext->next;
4750       PetscCall(PetscFree(iprev));
4751     }
4752     prev = next;
4753     next = next->next;
4754     PetscCall(PetscFree(prev));
4755   }
4756   MatSolverTypeHolders = NULL;
4757   PetscFunctionReturn(PETSC_SUCCESS);
4758 }
4759 
4760 /*@
4761   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4762 
4763   Logically Collective
4764 
4765   Input Parameter:
4766 . mat - the matrix
4767 
4768   Output Parameter:
4769 . flg - `PETSC_TRUE` if uses the ordering
4770 
4771   Level: developer
4772 
4773   Note:
4774   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4775   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4776 
4777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4778 @*/
4779 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4780 {
4781   PetscFunctionBegin;
4782   *flg = mat->canuseordering;
4783   PetscFunctionReturn(PETSC_SUCCESS);
4784 }
4785 
4786 /*@
4787   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4788 
4789   Logically Collective
4790 
4791   Input Parameters:
4792 + mat   - the matrix obtained with `MatGetFactor()`
4793 - ftype - the factorization type to be used
4794 
4795   Output Parameter:
4796 . otype - the preferred ordering type
4797 
4798   Level: developer
4799 
4800 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4801 @*/
4802 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4803 {
4804   PetscFunctionBegin;
4805   *otype = mat->preferredordering[ftype];
4806   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4807   PetscFunctionReturn(PETSC_SUCCESS);
4808 }
4809 
4810 /*@
4811   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4812 
4813   Collective
4814 
4815   Input Parameters:
4816 + mat   - the matrix
4817 . 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
4818           the other criteria is returned
4819 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4820 
4821   Output Parameter:
4822 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4823 
4824   Options Database Keys:
4825 + -pc_factor_mat_solver_type <type>    - choose the type at run time. When using `KSP` solvers
4826 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device
4827 - -pc_factor_mat_solve_on_host <bool>  - do mat solve on host (with device matrices). Default is doing it on device
4828 
4829   Level: intermediate
4830 
4831   Notes:
4832   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4833   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4834 
4835   Users usually access the factorization solvers via `KSP`
4836 
4837   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4838   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
4839 
4840   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4841   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4842   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4843 
4844   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4845   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4846   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4847 
4848   Developer Note:
4849   This should actually be called `MatCreateFactor()` since it creates a new factor object
4850 
4851 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4852           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4853           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4854 @*/
4855 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4856 {
4857   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4858   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4859 
4860   PetscFunctionBegin;
4861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4862   PetscValidType(mat, 1);
4863 
4864   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4865   MatCheckPreallocated(mat, 1);
4866 
4867   PetscCall(MatIsShell(mat, &shell));
4868   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4869   if (hasop) {
4870     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4871     PetscFunctionReturn(PETSC_SUCCESS);
4872   }
4873 
4874   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4875   if (!foundtype) {
4876     if (type) {
4877       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],
4878               ((PetscObject)mat)->type_name, type);
4879     } else {
4880       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);
4881     }
4882   }
4883   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4884   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);
4885 
4886   PetscCall((*conv)(mat, ftype, f));
4887   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4888   PetscFunctionReturn(PETSC_SUCCESS);
4889 }
4890 
4891 /*@
4892   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4893 
4894   Not Collective
4895 
4896   Input Parameters:
4897 + mat   - the matrix
4898 . type  - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default)
4899 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4900 
4901   Output Parameter:
4902 . flg - PETSC_TRUE if the factorization is available
4903 
4904   Level: intermediate
4905 
4906   Notes:
4907   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4908   such as pastix, superlu, mumps etc.
4909 
4910   PETSc must have been ./configure to use the external solver, using the option --download-package
4911 
4912   Developer Note:
4913   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4914 
4915 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4916           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4917 @*/
4918 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4919 {
4920   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4921 
4922   PetscFunctionBegin;
4923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4924   PetscAssertPointer(flg, 4);
4925 
4926   *flg = PETSC_FALSE;
4927   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4928 
4929   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4930   MatCheckPreallocated(mat, 1);
4931 
4932   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4933   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4934   PetscFunctionReturn(PETSC_SUCCESS);
4935 }
4936 
4937 /*@
4938   MatDuplicate - Duplicates a matrix including the non-zero structure.
4939 
4940   Collective
4941 
4942   Input Parameters:
4943 + mat - the matrix
4944 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4945         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4946 
4947   Output Parameter:
4948 . M - pointer to place new matrix
4949 
4950   Level: intermediate
4951 
4952   Notes:
4953   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4954 
4955   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4956 
4957   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.
4958 
4959   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4960   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4961   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4962 
4963 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4964 @*/
4965 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4966 {
4967   Mat         B;
4968   VecType     vtype;
4969   PetscInt    i;
4970   PetscObject dm, container_h, container_d;
4971   void (*viewf)(void);
4972 
4973   PetscFunctionBegin;
4974   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4975   PetscValidType(mat, 1);
4976   PetscAssertPointer(M, 3);
4977   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4978   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4979   MatCheckPreallocated(mat, 1);
4980 
4981   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4982   PetscUseTypeMethod(mat, duplicate, op, M);
4983   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4984   B = *M;
4985 
4986   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4987   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4988   PetscCall(MatGetVecType(mat, &vtype));
4989   PetscCall(MatSetVecType(B, vtype));
4990 
4991   B->stencil.dim = mat->stencil.dim;
4992   B->stencil.noc = mat->stencil.noc;
4993   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4994     B->stencil.dims[i]   = mat->stencil.dims[i];
4995     B->stencil.starts[i] = mat->stencil.starts[i];
4996   }
4997 
4998   B->nooffproczerorows = mat->nooffproczerorows;
4999   B->nooffprocentries  = mat->nooffprocentries;
5000 
5001   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
5002   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
5003   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
5004   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
5005   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
5006   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
5007   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
5008   PetscCall(PetscObjectStateIncrease((PetscObject)B));
5009   PetscFunctionReturn(PETSC_SUCCESS);
5010 }
5011 
5012 /*@
5013   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
5014 
5015   Logically Collective
5016 
5017   Input Parameter:
5018 . mat - the matrix
5019 
5020   Output Parameter:
5021 . v - the diagonal of the matrix
5022 
5023   Level: intermediate
5024 
5025   Note:
5026   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5027   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5028   is larger than `ndiag`, the values of the remaining entries are unspecified.
5029 
5030   Currently only correct in parallel for square matrices.
5031 
5032 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5033 @*/
5034 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5035 {
5036   PetscFunctionBegin;
5037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5038   PetscValidType(mat, 1);
5039   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5040   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5041   MatCheckPreallocated(mat, 1);
5042   if (PetscDefined(USE_DEBUG)) {
5043     PetscInt nv, row, col, ndiag;
5044 
5045     PetscCall(VecGetLocalSize(v, &nv));
5046     PetscCall(MatGetLocalSize(mat, &row, &col));
5047     ndiag = PetscMin(row, col);
5048     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);
5049   }
5050 
5051   PetscUseTypeMethod(mat, getdiagonal, v);
5052   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5053   PetscFunctionReturn(PETSC_SUCCESS);
5054 }
5055 
5056 /*@
5057   MatGetRowMin - Gets the minimum value (of the real part) of each
5058   row of the matrix
5059 
5060   Logically Collective
5061 
5062   Input Parameter:
5063 . mat - the matrix
5064 
5065   Output Parameters:
5066 + v   - the vector for storing the maximums
5067 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5068 
5069   Level: intermediate
5070 
5071   Note:
5072   The result of this call are the same as if one converted the matrix to dense format
5073   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5074 
5075   This code is only implemented for a couple of matrix formats.
5076 
5077 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5078           `MatGetRowMax()`
5079 @*/
5080 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5081 {
5082   PetscFunctionBegin;
5083   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5084   PetscValidType(mat, 1);
5085   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5086   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5087 
5088   if (!mat->cmap->N) {
5089     PetscCall(VecSet(v, PETSC_MAX_REAL));
5090     if (idx) {
5091       PetscInt i, m = mat->rmap->n;
5092       for (i = 0; i < m; i++) idx[i] = -1;
5093     }
5094   } else {
5095     MatCheckPreallocated(mat, 1);
5096   }
5097   PetscUseTypeMethod(mat, getrowmin, v, idx);
5098   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5099   PetscFunctionReturn(PETSC_SUCCESS);
5100 }
5101 
5102 /*@
5103   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5104   row of the matrix
5105 
5106   Logically Collective
5107 
5108   Input Parameter:
5109 . mat - the matrix
5110 
5111   Output Parameters:
5112 + v   - the vector for storing the minimums
5113 - idx - the indices of the column found for each row (or `NULL` if not needed)
5114 
5115   Level: intermediate
5116 
5117   Notes:
5118   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5119   row is 0 (the first column).
5120 
5121   This code is only implemented for a couple of matrix formats.
5122 
5123 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5124 @*/
5125 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5126 {
5127   PetscFunctionBegin;
5128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5129   PetscValidType(mat, 1);
5130   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5131   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5132   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5133 
5134   if (!mat->cmap->N) {
5135     PetscCall(VecSet(v, 0.0));
5136     if (idx) {
5137       PetscInt i, m = mat->rmap->n;
5138       for (i = 0; i < m; i++) idx[i] = -1;
5139     }
5140   } else {
5141     MatCheckPreallocated(mat, 1);
5142     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5143     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5144   }
5145   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5146   PetscFunctionReturn(PETSC_SUCCESS);
5147 }
5148 
5149 /*@
5150   MatGetRowMax - Gets the maximum value (of the real part) of each
5151   row of the matrix
5152 
5153   Logically Collective
5154 
5155   Input Parameter:
5156 . mat - the matrix
5157 
5158   Output Parameters:
5159 + v   - the vector for storing the maximums
5160 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5161 
5162   Level: intermediate
5163 
5164   Notes:
5165   The result of this call are the same as if one converted the matrix to dense format
5166   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5167 
5168   This code is only implemented for a couple of matrix formats.
5169 
5170 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5171 @*/
5172 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5173 {
5174   PetscFunctionBegin;
5175   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5176   PetscValidType(mat, 1);
5177   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5178   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5179 
5180   if (!mat->cmap->N) {
5181     PetscCall(VecSet(v, PETSC_MIN_REAL));
5182     if (idx) {
5183       PetscInt i, m = mat->rmap->n;
5184       for (i = 0; i < m; i++) idx[i] = -1;
5185     }
5186   } else {
5187     MatCheckPreallocated(mat, 1);
5188     PetscUseTypeMethod(mat, getrowmax, v, idx);
5189   }
5190   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5191   PetscFunctionReturn(PETSC_SUCCESS);
5192 }
5193 
5194 /*@
5195   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5196   row of the matrix
5197 
5198   Logically Collective
5199 
5200   Input Parameter:
5201 . mat - the matrix
5202 
5203   Output Parameters:
5204 + v   - the vector for storing the maximums
5205 - idx - the indices of the column found for each row (or `NULL` if not needed)
5206 
5207   Level: intermediate
5208 
5209   Notes:
5210   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5211   row is 0 (the first column).
5212 
5213   This code is only implemented for a couple of matrix formats.
5214 
5215 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5216 @*/
5217 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5218 {
5219   PetscFunctionBegin;
5220   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5221   PetscValidType(mat, 1);
5222   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5223   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5224 
5225   if (!mat->cmap->N) {
5226     PetscCall(VecSet(v, 0.0));
5227     if (idx) {
5228       PetscInt i, m = mat->rmap->n;
5229       for (i = 0; i < m; i++) idx[i] = -1;
5230     }
5231   } else {
5232     MatCheckPreallocated(mat, 1);
5233     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5234     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5235   }
5236   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5237   PetscFunctionReturn(PETSC_SUCCESS);
5238 }
5239 
5240 /*@
5241   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5242 
5243   Logically Collective
5244 
5245   Input Parameter:
5246 . mat - the matrix
5247 
5248   Output Parameter:
5249 . v - the vector for storing the sum
5250 
5251   Level: intermediate
5252 
5253   This code is only implemented for a couple of matrix formats.
5254 
5255 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5256 @*/
5257 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5258 {
5259   PetscFunctionBegin;
5260   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5261   PetscValidType(mat, 1);
5262   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5263   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5264 
5265   if (!mat->cmap->N) {
5266     PetscCall(VecSet(v, 0.0));
5267   } else {
5268     MatCheckPreallocated(mat, 1);
5269     PetscUseTypeMethod(mat, getrowsumabs, v);
5270   }
5271   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5272   PetscFunctionReturn(PETSC_SUCCESS);
5273 }
5274 
5275 /*@
5276   MatGetRowSum - Gets the sum of each row of the matrix
5277 
5278   Logically or Neighborhood Collective
5279 
5280   Input Parameter:
5281 . mat - the matrix
5282 
5283   Output Parameter:
5284 . v - the vector for storing the sum of rows
5285 
5286   Level: intermediate
5287 
5288   Note:
5289   This code is slow since it is not currently specialized for different formats
5290 
5291 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5292 @*/
5293 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5294 {
5295   Vec ones;
5296 
5297   PetscFunctionBegin;
5298   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5299   PetscValidType(mat, 1);
5300   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5301   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5302   MatCheckPreallocated(mat, 1);
5303   PetscCall(MatCreateVecs(mat, &ones, NULL));
5304   PetscCall(VecSet(ones, 1.));
5305   PetscCall(MatMult(mat, ones, v));
5306   PetscCall(VecDestroy(&ones));
5307   PetscFunctionReturn(PETSC_SUCCESS);
5308 }
5309 
5310 /*@
5311   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5312   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5313 
5314   Collective
5315 
5316   Input Parameter:
5317 . mat - the matrix to provide the transpose
5318 
5319   Output Parameter:
5320 . 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
5321 
5322   Level: advanced
5323 
5324   Note:
5325   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
5326   routine allows bypassing that call.
5327 
5328 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5329 @*/
5330 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5331 {
5332   MatParentState *rb = NULL;
5333 
5334   PetscFunctionBegin;
5335   PetscCall(PetscNew(&rb));
5336   rb->id    = ((PetscObject)mat)->id;
5337   rb->state = 0;
5338   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5339   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5340   PetscFunctionReturn(PETSC_SUCCESS);
5341 }
5342 
5343 /*@
5344   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5345 
5346   Collective
5347 
5348   Input Parameters:
5349 + mat   - the matrix to transpose
5350 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5351 
5352   Output Parameter:
5353 . B - the transpose of the matrix
5354 
5355   Level: intermediate
5356 
5357   Notes:
5358   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5359 
5360   `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the
5361   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5362 
5363   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.
5364 
5365   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5366   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5367 
5368   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5369 
5370   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5371 
5372 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5373           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5374 @*/
5375 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5376 {
5377   PetscContainer  rB = NULL;
5378   MatParentState *rb = NULL;
5379 
5380   PetscFunctionBegin;
5381   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5382   PetscValidType(mat, 1);
5383   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5384   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5385   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5386   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5387   MatCheckPreallocated(mat, 1);
5388   if (reuse == MAT_REUSE_MATRIX) {
5389     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5390     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5391     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5392     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5393     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5394   }
5395 
5396   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5397   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5398     PetscUseTypeMethod(mat, transpose, reuse, B);
5399     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5400   }
5401   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5402 
5403   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5404   if (reuse != MAT_INPLACE_MATRIX) {
5405     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5406     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5407     rb->state        = ((PetscObject)mat)->state;
5408     rb->nonzerostate = mat->nonzerostate;
5409   }
5410   PetscFunctionReturn(PETSC_SUCCESS);
5411 }
5412 
5413 /*@
5414   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5415 
5416   Collective
5417 
5418   Input Parameter:
5419 . A - the matrix to transpose
5420 
5421   Output Parameter:
5422 . 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
5423       numerical portion.
5424 
5425   Level: intermediate
5426 
5427   Note:
5428   This is not supported for many matrix types, use `MatTranspose()` in those cases
5429 
5430 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5431 @*/
5432 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5433 {
5434   PetscFunctionBegin;
5435   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5436   PetscValidType(A, 1);
5437   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5438   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5439   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5440   PetscUseTypeMethod(A, transposesymbolic, B);
5441   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5442 
5443   PetscCall(MatTransposeSetPrecursor(A, *B));
5444   PetscFunctionReturn(PETSC_SUCCESS);
5445 }
5446 
5447 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5448 {
5449   PetscContainer  rB;
5450   MatParentState *rb;
5451 
5452   PetscFunctionBegin;
5453   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5454   PetscValidType(A, 1);
5455   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5456   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5457   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5458   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5459   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5460   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5461   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5462   PetscFunctionReturn(PETSC_SUCCESS);
5463 }
5464 
5465 /*@
5466   MatIsTranspose - Test whether a matrix is another one's transpose,
5467   or its own, in which case it tests symmetry.
5468 
5469   Collective
5470 
5471   Input Parameters:
5472 + A   - the matrix to test
5473 . B   - the matrix to test against, this can equal the first parameter
5474 - tol - tolerance, differences between entries smaller than this are counted as zero
5475 
5476   Output Parameter:
5477 . flg - the result
5478 
5479   Level: intermediate
5480 
5481   Notes:
5482   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5483   test involves parallel copies of the block off-diagonal parts of the matrix.
5484 
5485 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5486 @*/
5487 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5488 {
5489   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5490 
5491   PetscFunctionBegin;
5492   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5493   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5494   PetscAssertPointer(flg, 4);
5495   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5496   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5497   *flg = PETSC_FALSE;
5498   if (f && g) {
5499     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5500     PetscCall((*f)(A, B, tol, flg));
5501   } else {
5502     MatType mattype;
5503 
5504     PetscCall(MatGetType(f ? B : A, &mattype));
5505     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5506   }
5507   PetscFunctionReturn(PETSC_SUCCESS);
5508 }
5509 
5510 /*@
5511   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5512 
5513   Collective
5514 
5515   Input Parameters:
5516 + mat   - the matrix to transpose and complex conjugate
5517 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5518 
5519   Output Parameter:
5520 . B - the Hermitian transpose
5521 
5522   Level: intermediate
5523 
5524 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5525 @*/
5526 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5527 {
5528   PetscFunctionBegin;
5529   PetscCall(MatTranspose(mat, reuse, B));
5530 #if defined(PETSC_USE_COMPLEX)
5531   PetscCall(MatConjugate(*B));
5532 #endif
5533   PetscFunctionReturn(PETSC_SUCCESS);
5534 }
5535 
5536 /*@
5537   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5538 
5539   Collective
5540 
5541   Input Parameters:
5542 + A   - the matrix to test
5543 . B   - the matrix to test against, this can equal the first parameter
5544 - tol - tolerance, differences between entries smaller than this are counted as zero
5545 
5546   Output Parameter:
5547 . flg - the result
5548 
5549   Level: intermediate
5550 
5551   Notes:
5552   Only available for `MATAIJ` matrices.
5553 
5554   The sequential algorithm
5555   has a running time of the order of the number of nonzeros; the parallel
5556   test involves parallel copies of the block off-diagonal parts of the matrix.
5557 
5558 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5559 @*/
5560 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5561 {
5562   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5563 
5564   PetscFunctionBegin;
5565   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5566   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5567   PetscAssertPointer(flg, 4);
5568   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5569   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5570   if (f && g) {
5571     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5572     PetscCall((*f)(A, B, tol, flg));
5573   }
5574   PetscFunctionReturn(PETSC_SUCCESS);
5575 }
5576 
5577 /*@
5578   MatPermute - Creates a new matrix with rows and columns permuted from the
5579   original.
5580 
5581   Collective
5582 
5583   Input Parameters:
5584 + mat - the matrix to permute
5585 . row - row permutation, each processor supplies only the permutation for its rows
5586 - col - column permutation, each processor supplies only the permutation for its columns
5587 
5588   Output Parameter:
5589 . B - the permuted matrix
5590 
5591   Level: advanced
5592 
5593   Note:
5594   The index sets map from row/col of permuted matrix to row/col of original matrix.
5595   The index sets should be on the same communicator as mat and have the same local sizes.
5596 
5597   Developer Note:
5598   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5599   exploit the fact that row and col are permutations, consider implementing the
5600   more general `MatCreateSubMatrix()` instead.
5601 
5602 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5603 @*/
5604 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5605 {
5606   PetscFunctionBegin;
5607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5608   PetscValidType(mat, 1);
5609   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5610   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5611   PetscAssertPointer(B, 4);
5612   PetscCheckSameComm(mat, 1, row, 2);
5613   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5614   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5615   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5616   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5617   MatCheckPreallocated(mat, 1);
5618 
5619   if (mat->ops->permute) {
5620     PetscUseTypeMethod(mat, permute, row, col, B);
5621     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5622   } else {
5623     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5624   }
5625   PetscFunctionReturn(PETSC_SUCCESS);
5626 }
5627 
5628 /*@
5629   MatEqual - Compares two matrices.
5630 
5631   Collective
5632 
5633   Input Parameters:
5634 + A - the first matrix
5635 - B - the second matrix
5636 
5637   Output Parameter:
5638 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5639 
5640   Level: intermediate
5641 
5642   Note:
5643   If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product
5644   using several randomly created vectors, see `MatMultEqual()`.
5645 
5646 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5647 @*/
5648 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5649 {
5650   PetscFunctionBegin;
5651   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5652   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5653   PetscValidType(A, 1);
5654   PetscValidType(B, 2);
5655   PetscAssertPointer(flg, 3);
5656   PetscCheckSameComm(A, 1, B, 2);
5657   MatCheckPreallocated(A, 1);
5658   MatCheckPreallocated(B, 2);
5659   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5660   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5661   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,
5662              B->cmap->N);
5663   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5664     PetscUseTypeMethod(A, equal, B, flg);
5665   } else {
5666     PetscCall(MatMultEqual(A, B, 10, flg));
5667   }
5668   PetscFunctionReturn(PETSC_SUCCESS);
5669 }
5670 
5671 /*@
5672   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5673   matrices that are stored as vectors.  Either of the two scaling
5674   matrices can be `NULL`.
5675 
5676   Collective
5677 
5678   Input Parameters:
5679 + mat - the matrix to be scaled
5680 . l   - the left scaling vector (or `NULL`)
5681 - r   - the right scaling vector (or `NULL`)
5682 
5683   Level: intermediate
5684 
5685   Note:
5686   `MatDiagonalScale()` computes $A = LAR$, where
5687   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5688   The L scales the rows of the matrix, the R scales the columns of the matrix.
5689 
5690 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5691 @*/
5692 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5693 {
5694   PetscFunctionBegin;
5695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5696   PetscValidType(mat, 1);
5697   if (l) {
5698     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5699     PetscCheckSameComm(mat, 1, l, 2);
5700   }
5701   if (r) {
5702     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5703     PetscCheckSameComm(mat, 1, r, 3);
5704   }
5705   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5706   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5707   MatCheckPreallocated(mat, 1);
5708   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5709 
5710   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5711   PetscUseTypeMethod(mat, diagonalscale, l, r);
5712   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5713   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5714   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5715   PetscFunctionReturn(PETSC_SUCCESS);
5716 }
5717 
5718 /*@
5719   MatScale - Scales all elements of a matrix by a given number.
5720 
5721   Logically Collective
5722 
5723   Input Parameters:
5724 + mat - the matrix to be scaled
5725 - a   - the scaling value
5726 
5727   Level: intermediate
5728 
5729 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5730 @*/
5731 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5732 {
5733   PetscFunctionBegin;
5734   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5735   PetscValidType(mat, 1);
5736   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5737   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5738   PetscValidLogicalCollectiveScalar(mat, a, 2);
5739   MatCheckPreallocated(mat, 1);
5740 
5741   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5742   if (a != (PetscScalar)1.0) {
5743     PetscUseTypeMethod(mat, scale, a);
5744     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5745   }
5746   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5747   PetscFunctionReturn(PETSC_SUCCESS);
5748 }
5749 
5750 /*@
5751   MatNorm - Calculates various norms of a matrix.
5752 
5753   Collective
5754 
5755   Input Parameters:
5756 + mat  - the matrix
5757 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5758 
5759   Output Parameter:
5760 . nrm - the resulting norm
5761 
5762   Level: intermediate
5763 
5764 .seealso: [](ch_matrices), `Mat`
5765 @*/
5766 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5767 {
5768   PetscFunctionBegin;
5769   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5770   PetscValidType(mat, 1);
5771   PetscAssertPointer(nrm, 3);
5772 
5773   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5774   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5775   MatCheckPreallocated(mat, 1);
5776 
5777   PetscUseTypeMethod(mat, norm, type, nrm);
5778   PetscFunctionReturn(PETSC_SUCCESS);
5779 }
5780 
5781 /*
5782      This variable is used to prevent counting of MatAssemblyBegin() that
5783    are called from within a MatAssemblyEnd().
5784 */
5785 static PetscInt MatAssemblyEnd_InUse = 0;
5786 /*@
5787   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5788   be called after completing all calls to `MatSetValues()`.
5789 
5790   Collective
5791 
5792   Input Parameters:
5793 + mat  - the matrix
5794 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5795 
5796   Level: beginner
5797 
5798   Notes:
5799   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5800   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5801 
5802   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5803   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5804   using the matrix.
5805 
5806   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5807   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
5808   a global collective operation requiring all processes that share the matrix.
5809 
5810   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5811   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5812   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5813 
5814 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5815 @*/
5816 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5817 {
5818   PetscFunctionBegin;
5819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5820   PetscValidType(mat, 1);
5821   MatCheckPreallocated(mat, 1);
5822   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5823   if (mat->assembled) {
5824     mat->was_assembled = PETSC_TRUE;
5825     mat->assembled     = PETSC_FALSE;
5826   }
5827 
5828   if (!MatAssemblyEnd_InUse) {
5829     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5830     PetscTryTypeMethod(mat, assemblybegin, type);
5831     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5832   } else PetscTryTypeMethod(mat, assemblybegin, type);
5833   PetscFunctionReturn(PETSC_SUCCESS);
5834 }
5835 
5836 /*@
5837   MatAssembled - Indicates if a matrix has been assembled and is ready for
5838   use; for example, in matrix-vector product.
5839 
5840   Not Collective
5841 
5842   Input Parameter:
5843 . mat - the matrix
5844 
5845   Output Parameter:
5846 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5847 
5848   Level: advanced
5849 
5850 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5851 @*/
5852 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5853 {
5854   PetscFunctionBegin;
5855   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5856   PetscAssertPointer(assembled, 2);
5857   *assembled = mat->assembled;
5858   PetscFunctionReturn(PETSC_SUCCESS);
5859 }
5860 
5861 /*@
5862   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5863   be called after `MatAssemblyBegin()`.
5864 
5865   Collective
5866 
5867   Input Parameters:
5868 + mat  - the matrix
5869 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5870 
5871   Options Database Keys:
5872 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5873 . -mat_view ::ascii_info_detail      - Prints more detailed info
5874 . -mat_view                          - Prints matrix in ASCII format
5875 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5876 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5877 . -display <name>                    - Sets display name (default is host)
5878 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5879 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5880 . -viewer_socket_machine <machine>   - Machine to use for socket
5881 . -viewer_socket_port <port>         - Port number to use for socket
5882 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5883 
5884   Level: beginner
5885 
5886 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5887 @*/
5888 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5889 {
5890   static PetscInt inassm = 0;
5891   PetscBool       flg    = PETSC_FALSE;
5892 
5893   PetscFunctionBegin;
5894   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5895   PetscValidType(mat, 1);
5896 
5897   inassm++;
5898   MatAssemblyEnd_InUse++;
5899   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5900     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5901     PetscTryTypeMethod(mat, assemblyend, type);
5902     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5903   } else PetscTryTypeMethod(mat, assemblyend, type);
5904 
5905   /* Flush assembly is not a true assembly */
5906   if (type != MAT_FLUSH_ASSEMBLY) {
5907     if (mat->num_ass) {
5908       if (!mat->symmetry_eternal) {
5909         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5910         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5911       }
5912       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5913       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5914     }
5915     mat->num_ass++;
5916     mat->assembled        = PETSC_TRUE;
5917     mat->ass_nonzerostate = mat->nonzerostate;
5918   }
5919 
5920   mat->insertmode = NOT_SET_VALUES;
5921   MatAssemblyEnd_InUse--;
5922   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5923   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5924     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5925 
5926     if (mat->checksymmetryonassembly) {
5927       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5928       if (flg) {
5929         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5930       } else {
5931         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5932       }
5933     }
5934     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5935   }
5936   inassm--;
5937   PetscFunctionReturn(PETSC_SUCCESS);
5938 }
5939 
5940 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5941 /*@
5942   MatSetOption - Sets a parameter option for a matrix. Some options
5943   may be specific to certain storage formats.  Some options
5944   determine how values will be inserted (or added). Sorted,
5945   row-oriented input will generally assemble the fastest. The default
5946   is row-oriented.
5947 
5948   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5949 
5950   Input Parameters:
5951 + mat - the matrix
5952 . op  - the option, one of those listed below (and possibly others),
5953 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5954 
5955   Options Describing Matrix Structure:
5956 + `MAT_SPD`                         - symmetric positive definite
5957 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5958 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5959 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5960 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5961 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5962 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5963 
5964    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5965    do not need to be computed (usually at a high cost)
5966 
5967    Options For Use with `MatSetValues()`:
5968    Insert a logically dense subblock, which can be
5969 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5970 
5971    These options reflect the data you pass in with `MatSetValues()`; it has
5972    nothing to do with how the data is stored internally in the matrix
5973    data structure.
5974 
5975    When (re)assembling a matrix, we can restrict the input for
5976    efficiency/debugging purposes.  These options include
5977 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5978 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5979 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5980 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5981 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5982 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5983         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5984         performance for very large process counts.
5985 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5986         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5987         functions, instead sending only neighbor messages.
5988 
5989   Level: intermediate
5990 
5991   Notes:
5992   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5993 
5994   Some options are relevant only for particular matrix types and
5995   are thus ignored by others.  Other options are not supported by
5996   certain matrix types and will generate an error message if set.
5997 
5998   If using Fortran to compute a matrix, one may need to
5999   use the column-oriented option (or convert to the row-oriented
6000   format).
6001 
6002   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
6003   that would generate a new entry in the nonzero structure is instead
6004   ignored.  Thus, if memory has not already been allocated for this particular
6005   data, then the insertion is ignored. For dense matrices, in which
6006   the entire array is allocated, no entries are ever ignored.
6007   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6008 
6009   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6010   that would generate a new entry in the nonzero structure instead produces
6011   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
6012 
6013   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6014   that would generate a new entry that has not been preallocated will
6015   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6016   only.) This is a useful flag when debugging matrix memory preallocation.
6017   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6018 
6019   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6020   other processors should be dropped, rather than stashed.
6021   This is useful if you know that the "owning" processor is also
6022   always generating the correct matrix entries, so that PETSc need
6023   not transfer duplicate entries generated on another processor.
6024 
6025   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6026   searches during matrix assembly. When this flag is set, the hash table
6027   is created during the first matrix assembly. This hash table is
6028   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6029   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6030   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6031   supported by `MATMPIBAIJ` format only.
6032 
6033   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6034   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6035 
6036   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6037   a zero location in the matrix
6038 
6039   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6040 
6041   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6042   zero row routines and thus improves performance for very large process counts.
6043 
6044   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6045   part of the matrix (since they should match the upper triangular part).
6046 
6047   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6048   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6049   with finite difference schemes with non-periodic boundary conditions.
6050 
6051   Developer Note:
6052   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6053   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6054   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6055   not changed.
6056 
6057 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6058 @*/
6059 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6060 {
6061   PetscFunctionBegin;
6062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6063   if (op > 0) {
6064     PetscValidLogicalCollectiveEnum(mat, op, 2);
6065     PetscValidLogicalCollectiveBool(mat, flg, 3);
6066   }
6067 
6068   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);
6069 
6070   switch (op) {
6071   case MAT_FORCE_DIAGONAL_ENTRIES:
6072     mat->force_diagonals = flg;
6073     PetscFunctionReturn(PETSC_SUCCESS);
6074   case MAT_NO_OFF_PROC_ENTRIES:
6075     mat->nooffprocentries = flg;
6076     PetscFunctionReturn(PETSC_SUCCESS);
6077   case MAT_SUBSET_OFF_PROC_ENTRIES:
6078     mat->assembly_subset = flg;
6079     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6080 #if !defined(PETSC_HAVE_MPIUNI)
6081       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6082 #endif
6083       mat->stash.first_assembly_done = PETSC_FALSE;
6084     }
6085     PetscFunctionReturn(PETSC_SUCCESS);
6086   case MAT_NO_OFF_PROC_ZERO_ROWS:
6087     mat->nooffproczerorows = flg;
6088     PetscFunctionReturn(PETSC_SUCCESS);
6089   case MAT_SPD:
6090     if (flg) {
6091       mat->spd                    = PETSC_BOOL3_TRUE;
6092       mat->symmetric              = PETSC_BOOL3_TRUE;
6093       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6094     } else {
6095       mat->spd = PETSC_BOOL3_FALSE;
6096     }
6097     break;
6098   case MAT_SYMMETRIC:
6099     mat->symmetric = PetscBoolToBool3(flg);
6100     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6101 #if !defined(PETSC_USE_COMPLEX)
6102     mat->hermitian = PetscBoolToBool3(flg);
6103 #endif
6104     break;
6105   case MAT_HERMITIAN:
6106     mat->hermitian = PetscBoolToBool3(flg);
6107     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6108 #if !defined(PETSC_USE_COMPLEX)
6109     mat->symmetric = PetscBoolToBool3(flg);
6110 #endif
6111     break;
6112   case MAT_STRUCTURALLY_SYMMETRIC:
6113     mat->structurally_symmetric = PetscBoolToBool3(flg);
6114     break;
6115   case MAT_SYMMETRY_ETERNAL:
6116     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");
6117     mat->symmetry_eternal = flg;
6118     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6119     break;
6120   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6121     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");
6122     mat->structural_symmetry_eternal = flg;
6123     break;
6124   case MAT_SPD_ETERNAL:
6125     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");
6126     mat->spd_eternal = flg;
6127     if (flg) {
6128       mat->structural_symmetry_eternal = PETSC_TRUE;
6129       mat->symmetry_eternal            = PETSC_TRUE;
6130     }
6131     break;
6132   case MAT_STRUCTURE_ONLY:
6133     mat->structure_only = flg;
6134     break;
6135   case MAT_SORTED_FULL:
6136     mat->sortedfull = flg;
6137     break;
6138   default:
6139     break;
6140   }
6141   PetscTryTypeMethod(mat, setoption, op, flg);
6142   PetscFunctionReturn(PETSC_SUCCESS);
6143 }
6144 
6145 /*@
6146   MatGetOption - Gets a parameter option that has been set for a matrix.
6147 
6148   Logically Collective
6149 
6150   Input Parameters:
6151 + mat - the matrix
6152 - op  - the option, this only responds to certain options, check the code for which ones
6153 
6154   Output Parameter:
6155 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6156 
6157   Level: intermediate
6158 
6159   Notes:
6160   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6161 
6162   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6163   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6164 
6165 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6166     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6167 @*/
6168 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6169 {
6170   PetscFunctionBegin;
6171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6172   PetscValidType(mat, 1);
6173 
6174   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);
6175   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()");
6176 
6177   switch (op) {
6178   case MAT_NO_OFF_PROC_ENTRIES:
6179     *flg = mat->nooffprocentries;
6180     break;
6181   case MAT_NO_OFF_PROC_ZERO_ROWS:
6182     *flg = mat->nooffproczerorows;
6183     break;
6184   case MAT_SYMMETRIC:
6185     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6186     break;
6187   case MAT_HERMITIAN:
6188     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6189     break;
6190   case MAT_STRUCTURALLY_SYMMETRIC:
6191     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6192     break;
6193   case MAT_SPD:
6194     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6195     break;
6196   case MAT_SYMMETRY_ETERNAL:
6197     *flg = mat->symmetry_eternal;
6198     break;
6199   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6200     *flg = mat->symmetry_eternal;
6201     break;
6202   default:
6203     break;
6204   }
6205   PetscFunctionReturn(PETSC_SUCCESS);
6206 }
6207 
6208 /*@
6209   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6210   this routine retains the old nonzero structure.
6211 
6212   Logically Collective
6213 
6214   Input Parameter:
6215 . mat - the matrix
6216 
6217   Level: intermediate
6218 
6219   Note:
6220   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.
6221   See the Performance chapter of the users manual for information on preallocating matrices.
6222 
6223 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6224 @*/
6225 PetscErrorCode MatZeroEntries(Mat mat)
6226 {
6227   PetscFunctionBegin;
6228   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6229   PetscValidType(mat, 1);
6230   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6231   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");
6232   MatCheckPreallocated(mat, 1);
6233 
6234   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6235   PetscUseTypeMethod(mat, zeroentries);
6236   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6237   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6238   PetscFunctionReturn(PETSC_SUCCESS);
6239 }
6240 
6241 /*@
6242   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6243   of a set of rows and columns of a matrix.
6244 
6245   Collective
6246 
6247   Input Parameters:
6248 + mat     - the matrix
6249 . numRows - the number of rows/columns to zero
6250 . rows    - the global row indices
6251 . diag    - value put in the diagonal of the eliminated rows
6252 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6253 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6254 
6255   Level: intermediate
6256 
6257   Notes:
6258   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6259 
6260   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6261   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
6262 
6263   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6264   Krylov method to take advantage of the known solution on the zeroed rows.
6265 
6266   For the parallel case, all processes that share the matrix (i.e.,
6267   those in the communicator used for matrix creation) MUST call this
6268   routine, regardless of whether any rows being zeroed are owned by
6269   them.
6270 
6271   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6272   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
6273   missing.
6274 
6275   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6276   list only rows local to itself).
6277 
6278   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6279 
6280 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6281           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6282 @*/
6283 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6284 {
6285   PetscFunctionBegin;
6286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6287   PetscValidType(mat, 1);
6288   if (numRows) PetscAssertPointer(rows, 3);
6289   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6290   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6291   MatCheckPreallocated(mat, 1);
6292 
6293   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6294   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6295   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6296   PetscFunctionReturn(PETSC_SUCCESS);
6297 }
6298 
6299 /*@
6300   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6301   of a set of rows and columns of a matrix.
6302 
6303   Collective
6304 
6305   Input Parameters:
6306 + mat  - the matrix
6307 . is   - the rows to zero
6308 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6309 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6310 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6311 
6312   Level: intermediate
6313 
6314   Note:
6315   See `MatZeroRowsColumns()` for details on how this routine operates.
6316 
6317 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6318           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6319 @*/
6320 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6321 {
6322   PetscInt        numRows;
6323   const PetscInt *rows;
6324 
6325   PetscFunctionBegin;
6326   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6327   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6328   PetscValidType(mat, 1);
6329   PetscValidType(is, 2);
6330   PetscCall(ISGetLocalSize(is, &numRows));
6331   PetscCall(ISGetIndices(is, &rows));
6332   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6333   PetscCall(ISRestoreIndices(is, &rows));
6334   PetscFunctionReturn(PETSC_SUCCESS);
6335 }
6336 
6337 /*@
6338   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6339   of a set of rows of a matrix.
6340 
6341   Collective
6342 
6343   Input Parameters:
6344 + mat     - the matrix
6345 . numRows - the number of rows to zero
6346 . rows    - the global row indices
6347 . diag    - value put in the diagonal of the zeroed rows
6348 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6349 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6350 
6351   Level: intermediate
6352 
6353   Notes:
6354   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6355 
6356   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6357 
6358   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6359   Krylov method to take advantage of the known solution on the zeroed rows.
6360 
6361   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)
6362   from the matrix.
6363 
6364   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6365   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6366   formats this does not alter the nonzero structure.
6367 
6368   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6369   of the matrix is not changed the values are
6370   merely zeroed.
6371 
6372   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6373   formats can optionally remove the main diagonal entry from the
6374   nonzero structure as well, by passing 0.0 as the final argument).
6375 
6376   For the parallel case, all processes that share the matrix (i.e.,
6377   those in the communicator used for matrix creation) MUST call this
6378   routine, regardless of whether any rows being zeroed are owned by
6379   them.
6380 
6381   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6382   list only rows local to itself).
6383 
6384   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6385   owns that are to be zeroed. This saves a global synchronization in the implementation.
6386 
6387 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6388           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6389 @*/
6390 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6391 {
6392   PetscFunctionBegin;
6393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6394   PetscValidType(mat, 1);
6395   if (numRows) PetscAssertPointer(rows, 3);
6396   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6397   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6398   MatCheckPreallocated(mat, 1);
6399 
6400   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6401   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6402   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6403   PetscFunctionReturn(PETSC_SUCCESS);
6404 }
6405 
6406 /*@
6407   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6408   of a set of rows of a matrix indicated by an `IS`
6409 
6410   Collective
6411 
6412   Input Parameters:
6413 + mat  - the matrix
6414 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6415 . diag - value put in all diagonals of eliminated rows
6416 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6417 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6418 
6419   Level: intermediate
6420 
6421   Note:
6422   See `MatZeroRows()` for details on how this routine operates.
6423 
6424 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6425           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6426 @*/
6427 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6428 {
6429   PetscInt        numRows = 0;
6430   const PetscInt *rows    = NULL;
6431 
6432   PetscFunctionBegin;
6433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6434   PetscValidType(mat, 1);
6435   if (is) {
6436     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6437     PetscCall(ISGetLocalSize(is, &numRows));
6438     PetscCall(ISGetIndices(is, &rows));
6439   }
6440   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6441   if (is) PetscCall(ISRestoreIndices(is, &rows));
6442   PetscFunctionReturn(PETSC_SUCCESS);
6443 }
6444 
6445 /*@
6446   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6447   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6448 
6449   Collective
6450 
6451   Input Parameters:
6452 + mat     - the matrix
6453 . numRows - the number of rows to remove
6454 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6455 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6456 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6457 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6458 
6459   Level: intermediate
6460 
6461   Notes:
6462   See `MatZeroRows()` for details on how this routine operates.
6463 
6464   The grid coordinates are across the entire grid, not just the local portion
6465 
6466   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6467   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6468   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6469   `DM_BOUNDARY_PERIODIC` boundary type.
6470 
6471   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
6472   a single value per point) you can skip filling those indices.
6473 
6474   Fortran Note:
6475   `idxm` and `idxn` should be declared as
6476 .vb
6477     MatStencil idxm(4, m)
6478 .ve
6479   and the values inserted using
6480 .vb
6481     idxm(MatStencil_i, 1) = i
6482     idxm(MatStencil_j, 1) = j
6483     idxm(MatStencil_k, 1) = k
6484     idxm(MatStencil_c, 1) = c
6485    etc
6486 .ve
6487 
6488 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6489           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6490 @*/
6491 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6492 {
6493   PetscInt  dim    = mat->stencil.dim;
6494   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6495   PetscInt *dims   = mat->stencil.dims + 1;
6496   PetscInt *starts = mat->stencil.starts;
6497   PetscInt *dxm    = (PetscInt *)rows;
6498   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6499 
6500   PetscFunctionBegin;
6501   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6502   PetscValidType(mat, 1);
6503   if (numRows) PetscAssertPointer(rows, 3);
6504 
6505   PetscCall(PetscMalloc1(numRows, &jdxm));
6506   for (i = 0; i < numRows; ++i) {
6507     /* Skip unused dimensions (they are ordered k, j, i, c) */
6508     for (j = 0; j < 3 - sdim; ++j) dxm++;
6509     /* Local index in X dir */
6510     tmp = *dxm++ - starts[0];
6511     /* Loop over remaining dimensions */
6512     for (j = 0; j < dim - 1; ++j) {
6513       /* If nonlocal, set index to be negative */
6514       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6515       /* Update local index */
6516       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6517     }
6518     /* Skip component slot if necessary */
6519     if (mat->stencil.noc) dxm++;
6520     /* Local row number */
6521     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6522   }
6523   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6524   PetscCall(PetscFree(jdxm));
6525   PetscFunctionReturn(PETSC_SUCCESS);
6526 }
6527 
6528 /*@
6529   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6530   of a set of rows and columns of a matrix.
6531 
6532   Collective
6533 
6534   Input Parameters:
6535 + mat     - the matrix
6536 . numRows - the number of rows/columns to remove
6537 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6538 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6539 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6540 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6541 
6542   Level: intermediate
6543 
6544   Notes:
6545   See `MatZeroRowsColumns()` for details on how this routine operates.
6546 
6547   The grid coordinates are across the entire grid, not just the local portion
6548 
6549   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6550   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6551   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6552   `DM_BOUNDARY_PERIODIC` boundary type.
6553 
6554   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
6555   a single value per point) you can skip filling those indices.
6556 
6557   Fortran Note:
6558   `idxm` and `idxn` should be declared as
6559 .vb
6560     MatStencil idxm(4, m)
6561 .ve
6562   and the values inserted using
6563 .vb
6564     idxm(MatStencil_i, 1) = i
6565     idxm(MatStencil_j, 1) = j
6566     idxm(MatStencil_k, 1) = k
6567     idxm(MatStencil_c, 1) = c
6568     etc
6569 .ve
6570 
6571 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6572           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6573 @*/
6574 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6575 {
6576   PetscInt  dim    = mat->stencil.dim;
6577   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6578   PetscInt *dims   = mat->stencil.dims + 1;
6579   PetscInt *starts = mat->stencil.starts;
6580   PetscInt *dxm    = (PetscInt *)rows;
6581   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6582 
6583   PetscFunctionBegin;
6584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6585   PetscValidType(mat, 1);
6586   if (numRows) PetscAssertPointer(rows, 3);
6587 
6588   PetscCall(PetscMalloc1(numRows, &jdxm));
6589   for (i = 0; i < numRows; ++i) {
6590     /* Skip unused dimensions (they are ordered k, j, i, c) */
6591     for (j = 0; j < 3 - sdim; ++j) dxm++;
6592     /* Local index in X dir */
6593     tmp = *dxm++ - starts[0];
6594     /* Loop over remaining dimensions */
6595     for (j = 0; j < dim - 1; ++j) {
6596       /* If nonlocal, set index to be negative */
6597       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6598       /* Update local index */
6599       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6600     }
6601     /* Skip component slot if necessary */
6602     if (mat->stencil.noc) dxm++;
6603     /* Local row number */
6604     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6605   }
6606   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6607   PetscCall(PetscFree(jdxm));
6608   PetscFunctionReturn(PETSC_SUCCESS);
6609 }
6610 
6611 /*@
6612   MatZeroRowsLocal - 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 . numRows - the number of rows to remove
6620 . rows    - the local row indices
6621 . diag    - value put in all diagonals of eliminated rows
6622 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6623 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6624 
6625   Level: intermediate
6626 
6627   Notes:
6628   Before calling `MatZeroRowsLocal()`, the user must first set the
6629   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6630 
6631   See `MatZeroRows()` for details on how this routine operates.
6632 
6633 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6634           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6635 @*/
6636 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6637 {
6638   PetscFunctionBegin;
6639   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6640   PetscValidType(mat, 1);
6641   if (numRows) PetscAssertPointer(rows, 3);
6642   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6643   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6644   MatCheckPreallocated(mat, 1);
6645 
6646   if (mat->ops->zerorowslocal) {
6647     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6648   } else {
6649     IS              is, newis;
6650     const PetscInt *newRows;
6651 
6652     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6653     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6654     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6655     PetscCall(ISGetIndices(newis, &newRows));
6656     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6657     PetscCall(ISRestoreIndices(newis, &newRows));
6658     PetscCall(ISDestroy(&newis));
6659     PetscCall(ISDestroy(&is));
6660   }
6661   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6662   PetscFunctionReturn(PETSC_SUCCESS);
6663 }
6664 
6665 /*@
6666   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6667   of a set of rows of a matrix; using local numbering of rows.
6668 
6669   Collective
6670 
6671   Input Parameters:
6672 + mat  - the matrix
6673 . is   - index set of rows to remove
6674 . diag - value put in all diagonals of eliminated rows
6675 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6676 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6677 
6678   Level: intermediate
6679 
6680   Notes:
6681   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6682   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6683 
6684   See `MatZeroRows()` for details on how this routine operates.
6685 
6686 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6687           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6688 @*/
6689 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6690 {
6691   PetscInt        numRows;
6692   const PetscInt *rows;
6693 
6694   PetscFunctionBegin;
6695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6696   PetscValidType(mat, 1);
6697   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6698   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6699   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6700   MatCheckPreallocated(mat, 1);
6701 
6702   PetscCall(ISGetLocalSize(is, &numRows));
6703   PetscCall(ISGetIndices(is, &rows));
6704   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6705   PetscCall(ISRestoreIndices(is, &rows));
6706   PetscFunctionReturn(PETSC_SUCCESS);
6707 }
6708 
6709 /*@
6710   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6711   of a set of rows and columns of a matrix; using local numbering of rows.
6712 
6713   Collective
6714 
6715   Input Parameters:
6716 + mat     - the matrix
6717 . numRows - the number of rows to remove
6718 . rows    - the global row indices
6719 . diag    - value put in all diagonals of eliminated rows
6720 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6721 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6722 
6723   Level: intermediate
6724 
6725   Notes:
6726   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6727   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6728 
6729   See `MatZeroRowsColumns()` for details on how this routine operates.
6730 
6731 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6732           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6733 @*/
6734 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6735 {
6736   IS              is, newis;
6737   const PetscInt *newRows;
6738 
6739   PetscFunctionBegin;
6740   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6741   PetscValidType(mat, 1);
6742   if (numRows) PetscAssertPointer(rows, 3);
6743   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6744   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6745   MatCheckPreallocated(mat, 1);
6746 
6747   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6748   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6749   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6750   PetscCall(ISGetIndices(newis, &newRows));
6751   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6752   PetscCall(ISRestoreIndices(newis, &newRows));
6753   PetscCall(ISDestroy(&newis));
6754   PetscCall(ISDestroy(&is));
6755   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6756   PetscFunctionReturn(PETSC_SUCCESS);
6757 }
6758 
6759 /*@
6760   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6761   of a set of rows and columns of a matrix; using local numbering of rows.
6762 
6763   Collective
6764 
6765   Input Parameters:
6766 + mat  - the matrix
6767 . is   - index set of rows to remove
6768 . diag - value put in all diagonals of eliminated rows
6769 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6770 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6771 
6772   Level: intermediate
6773 
6774   Notes:
6775   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6776   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6777 
6778   See `MatZeroRowsColumns()` for details on how this routine operates.
6779 
6780 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6781           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6782 @*/
6783 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6784 {
6785   PetscInt        numRows;
6786   const PetscInt *rows;
6787 
6788   PetscFunctionBegin;
6789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6790   PetscValidType(mat, 1);
6791   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6792   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6793   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6794   MatCheckPreallocated(mat, 1);
6795 
6796   PetscCall(ISGetLocalSize(is, &numRows));
6797   PetscCall(ISGetIndices(is, &rows));
6798   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6799   PetscCall(ISRestoreIndices(is, &rows));
6800   PetscFunctionReturn(PETSC_SUCCESS);
6801 }
6802 
6803 /*@
6804   MatGetSize - Returns the numbers of rows and columns in a matrix.
6805 
6806   Not Collective
6807 
6808   Input Parameter:
6809 . mat - the matrix
6810 
6811   Output Parameters:
6812 + m - the number of global rows
6813 - n - the number of global columns
6814 
6815   Level: beginner
6816 
6817   Note:
6818   Both output parameters can be `NULL` on input.
6819 
6820 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6821 @*/
6822 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6823 {
6824   PetscFunctionBegin;
6825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6826   if (m) *m = mat->rmap->N;
6827   if (n) *n = mat->cmap->N;
6828   PetscFunctionReturn(PETSC_SUCCESS);
6829 }
6830 
6831 /*@
6832   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6833   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6834 
6835   Not Collective
6836 
6837   Input Parameter:
6838 . mat - the matrix
6839 
6840   Output Parameters:
6841 + m - the number of local rows, use `NULL` to not obtain this value
6842 - n - the number of local columns, use `NULL` to not obtain this value
6843 
6844   Level: beginner
6845 
6846 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6847 @*/
6848 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6849 {
6850   PetscFunctionBegin;
6851   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6852   if (m) PetscAssertPointer(m, 2);
6853   if (n) PetscAssertPointer(n, 3);
6854   if (m) *m = mat->rmap->n;
6855   if (n) *n = mat->cmap->n;
6856   PetscFunctionReturn(PETSC_SUCCESS);
6857 }
6858 
6859 /*@
6860   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6861   vector one multiplies this matrix by that are owned by this processor.
6862 
6863   Not Collective, unless matrix has not been allocated, then collective
6864 
6865   Input Parameter:
6866 . mat - the matrix
6867 
6868   Output Parameters:
6869 + m - the global index of the first local column, use `NULL` to not obtain this value
6870 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6871 
6872   Level: developer
6873 
6874   Notes:
6875   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6876 
6877   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6878   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6879 
6880   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6881   the local values in the matrix.
6882 
6883   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6884   Layouts](sec_matlayout) for details on matrix layouts.
6885 
6886 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6887           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6888 @*/
6889 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6890 {
6891   PetscFunctionBegin;
6892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6893   PetscValidType(mat, 1);
6894   if (m) PetscAssertPointer(m, 2);
6895   if (n) PetscAssertPointer(n, 3);
6896   MatCheckPreallocated(mat, 1);
6897   if (m) *m = mat->cmap->rstart;
6898   if (n) *n = mat->cmap->rend;
6899   PetscFunctionReturn(PETSC_SUCCESS);
6900 }
6901 
6902 /*@
6903   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6904   this MPI process.
6905 
6906   Not Collective
6907 
6908   Input Parameter:
6909 . mat - the matrix
6910 
6911   Output Parameters:
6912 + m - the global index of the first local row, use `NULL` to not obtain this value
6913 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6914 
6915   Level: beginner
6916 
6917   Notes:
6918   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6919 
6920   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6921   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6922 
6923   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6924   the local values in the matrix.
6925 
6926   The high argument is one more than the last element stored locally.
6927 
6928   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6929   would contain the result of a matrix vector product with this matrix. See [Matrix
6930   Layouts](sec_matlayout) for details on matrix layouts.
6931 
6932 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6933           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6934 @*/
6935 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6936 {
6937   PetscFunctionBegin;
6938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6939   PetscValidType(mat, 1);
6940   if (m) PetscAssertPointer(m, 2);
6941   if (n) PetscAssertPointer(n, 3);
6942   MatCheckPreallocated(mat, 1);
6943   if (m) *m = mat->rmap->rstart;
6944   if (n) *n = mat->rmap->rend;
6945   PetscFunctionReturn(PETSC_SUCCESS);
6946 }
6947 
6948 /*@C
6949   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6950   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6951 
6952   Not Collective, unless matrix has not been allocated
6953 
6954   Input Parameter:
6955 . mat - the matrix
6956 
6957   Output Parameter:
6958 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6959            where `size` is the number of MPI processes used by `mat`
6960 
6961   Level: beginner
6962 
6963   Notes:
6964   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6965 
6966   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6967   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6968 
6969   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6970   the local values in the matrix.
6971 
6972   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6973   would contain the result of a matrix vector product with this matrix. See [Matrix
6974   Layouts](sec_matlayout) for details on matrix layouts.
6975 
6976 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6977           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6978           `DMDAGetGhostCorners()`, `DM`
6979 @*/
6980 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6981 {
6982   PetscFunctionBegin;
6983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6984   PetscValidType(mat, 1);
6985   MatCheckPreallocated(mat, 1);
6986   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6987   PetscFunctionReturn(PETSC_SUCCESS);
6988 }
6989 
6990 /*@C
6991   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6992   vector one multiplies this vector by that are owned by each processor.
6993 
6994   Not Collective, unless matrix has not been allocated
6995 
6996   Input Parameter:
6997 . mat - the matrix
6998 
6999   Output Parameter:
7000 . ranges - start of each processors portion plus one more than the total length at the end
7001 
7002   Level: beginner
7003 
7004   Notes:
7005   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
7006 
7007   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7008   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7009 
7010   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7011   the local values in the matrix.
7012 
7013   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7014   Layouts](sec_matlayout) for details on matrix layouts.
7015 
7016 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7017           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7018           `DMDAGetGhostCorners()`, `DM`
7019 @*/
7020 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7021 {
7022   PetscFunctionBegin;
7023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7024   PetscValidType(mat, 1);
7025   MatCheckPreallocated(mat, 1);
7026   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7027   PetscFunctionReturn(PETSC_SUCCESS);
7028 }
7029 
7030 /*@
7031   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7032 
7033   Not Collective
7034 
7035   Input Parameter:
7036 . A - matrix
7037 
7038   Output Parameters:
7039 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7040 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7041 
7042   Level: intermediate
7043 
7044   Note:
7045   You should call `ISDestroy()` on the returned `IS`
7046 
7047   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7048   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7049   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7050   details on matrix layouts.
7051 
7052 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7053 @*/
7054 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7055 {
7056   PetscErrorCode (*f)(Mat, IS *, IS *);
7057 
7058   PetscFunctionBegin;
7059   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7060   PetscValidType(A, 1);
7061   MatCheckPreallocated(A, 1);
7062   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7063   if (f) {
7064     PetscCall((*f)(A, rows, cols));
7065   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7066     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7067     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7068   }
7069   PetscFunctionReturn(PETSC_SUCCESS);
7070 }
7071 
7072 /*@
7073   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7074   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7075   to complete the factorization.
7076 
7077   Collective
7078 
7079   Input Parameters:
7080 + fact - the factorized matrix obtained with `MatGetFactor()`
7081 . mat  - the matrix
7082 . row  - row permutation
7083 . col  - column permutation
7084 - info - structure containing
7085 .vb
7086       levels - number of levels of fill.
7087       expected fill - as ratio of original fill.
7088       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7089                 missing diagonal entries)
7090 .ve
7091 
7092   Level: developer
7093 
7094   Notes:
7095   See [Matrix Factorization](sec_matfactor) for additional information.
7096 
7097   Most users should employ the `KSP` interface for linear solvers
7098   instead of working directly with matrix algebra routines such as this.
7099   See, e.g., `KSPCreate()`.
7100 
7101   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7102 
7103   Developer Note:
7104   The Fortran interface is not autogenerated as the
7105   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7106 
7107 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7108           `MatGetOrdering()`, `MatFactorInfo`
7109 @*/
7110 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7111 {
7112   PetscFunctionBegin;
7113   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7114   PetscValidType(mat, 2);
7115   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7116   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7117   PetscAssertPointer(info, 5);
7118   PetscAssertPointer(fact, 1);
7119   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7120   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7121   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7122   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7123   MatCheckPreallocated(mat, 2);
7124 
7125   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7126   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7127   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7128   PetscFunctionReturn(PETSC_SUCCESS);
7129 }
7130 
7131 /*@
7132   MatICCFactorSymbolic - Performs symbolic incomplete
7133   Cholesky factorization for a symmetric matrix.  Use
7134   `MatCholeskyFactorNumeric()` to complete the factorization.
7135 
7136   Collective
7137 
7138   Input Parameters:
7139 + fact - the factorized matrix obtained with `MatGetFactor()`
7140 . mat  - the matrix to be factored
7141 . perm - row and column permutation
7142 - info - structure containing
7143 .vb
7144       levels - number of levels of fill.
7145       expected fill - as ratio of original fill.
7146 .ve
7147 
7148   Level: developer
7149 
7150   Notes:
7151   Most users should employ the `KSP` interface for linear solvers
7152   instead of working directly with matrix algebra routines such as this.
7153   See, e.g., `KSPCreate()`.
7154 
7155   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7156 
7157   Developer Note:
7158   The Fortran interface is not autogenerated as the
7159   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7160 
7161 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7162 @*/
7163 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7164 {
7165   PetscFunctionBegin;
7166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7167   PetscValidType(mat, 2);
7168   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7169   PetscAssertPointer(info, 4);
7170   PetscAssertPointer(fact, 1);
7171   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7172   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7173   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7174   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7175   MatCheckPreallocated(mat, 2);
7176 
7177   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7178   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7179   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7180   PetscFunctionReturn(PETSC_SUCCESS);
7181 }
7182 
7183 /*@C
7184   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7185   points to an array of valid matrices, they may be reused to store the new
7186   submatrices.
7187 
7188   Collective
7189 
7190   Input Parameters:
7191 + mat   - the matrix
7192 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7193 . irow  - index set of rows to extract
7194 . icol  - index set of columns to extract
7195 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7196 
7197   Output Parameter:
7198 . submat - the array of submatrices
7199 
7200   Level: advanced
7201 
7202   Notes:
7203   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7204   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7205   to extract a parallel submatrix.
7206 
7207   Some matrix types place restrictions on the row and column
7208   indices, such as that they be sorted or that they be equal to each other.
7209 
7210   The index sets may not have duplicate entries.
7211 
7212   When extracting submatrices from a parallel matrix, each processor can
7213   form a different submatrix by setting the rows and columns of its
7214   individual index sets according to the local submatrix desired.
7215 
7216   When finished using the submatrices, the user should destroy
7217   them with `MatDestroySubMatrices()`.
7218 
7219   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7220   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7221 
7222   This routine creates the matrices in submat; you should NOT create them before
7223   calling it. It also allocates the array of matrix pointers submat.
7224 
7225   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7226   request one row/column in a block, they must request all rows/columns that are in
7227   that block. For example, if the block size is 2 you cannot request just row 0 and
7228   column 0.
7229 
7230   Fortran Note:
7231 .vb
7232   Mat, pointer :: submat(:)
7233 .ve
7234 
7235 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7236 @*/
7237 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7238 {
7239   PetscInt  i;
7240   PetscBool eq;
7241 
7242   PetscFunctionBegin;
7243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7244   PetscValidType(mat, 1);
7245   if (n) {
7246     PetscAssertPointer(irow, 3);
7247     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7248     PetscAssertPointer(icol, 4);
7249     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7250   }
7251   PetscAssertPointer(submat, 6);
7252   if (n && scall == MAT_REUSE_MATRIX) {
7253     PetscAssertPointer(*submat, 6);
7254     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7255   }
7256   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7257   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7258   MatCheckPreallocated(mat, 1);
7259   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7260   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7261   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7262   for (i = 0; i < n; i++) {
7263     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7264     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7265     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7266 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7267     if (mat->boundtocpu && mat->bindingpropagates) {
7268       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7269       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7270     }
7271 #endif
7272   }
7273   PetscFunctionReturn(PETSC_SUCCESS);
7274 }
7275 
7276 /*@C
7277   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms).
7278 
7279   Collective
7280 
7281   Input Parameters:
7282 + mat   - the matrix
7283 . n     - the number of submatrixes to be extracted
7284 . irow  - index set of rows to extract
7285 . icol  - index set of columns to extract
7286 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7287 
7288   Output Parameter:
7289 . submat - the array of submatrices
7290 
7291   Level: advanced
7292 
7293   Note:
7294   This is used by `PCGASM`
7295 
7296 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7297 @*/
7298 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7299 {
7300   PetscInt  i;
7301   PetscBool eq;
7302 
7303   PetscFunctionBegin;
7304   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7305   PetscValidType(mat, 1);
7306   if (n) {
7307     PetscAssertPointer(irow, 3);
7308     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7309     PetscAssertPointer(icol, 4);
7310     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7311   }
7312   PetscAssertPointer(submat, 6);
7313   if (n && scall == MAT_REUSE_MATRIX) {
7314     PetscAssertPointer(*submat, 6);
7315     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7316   }
7317   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7318   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7319   MatCheckPreallocated(mat, 1);
7320 
7321   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7322   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7323   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7324   for (i = 0; i < n; i++) {
7325     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7326     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7327   }
7328   PetscFunctionReturn(PETSC_SUCCESS);
7329 }
7330 
7331 /*@C
7332   MatDestroyMatrices - Destroys an array of matrices
7333 
7334   Collective
7335 
7336   Input Parameters:
7337 + n   - the number of local matrices
7338 - mat - the matrices (this is a pointer to the array of matrices)
7339 
7340   Level: advanced
7341 
7342   Notes:
7343   Frees not only the matrices, but also the array that contains the matrices
7344 
7345   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7346 
7347 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7348 @*/
7349 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7350 {
7351   PetscInt i;
7352 
7353   PetscFunctionBegin;
7354   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7355   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7356   PetscAssertPointer(mat, 2);
7357 
7358   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7359 
7360   /* memory is allocated even if n = 0 */
7361   PetscCall(PetscFree(*mat));
7362   PetscFunctionReturn(PETSC_SUCCESS);
7363 }
7364 
7365 /*@C
7366   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7367 
7368   Collective
7369 
7370   Input Parameters:
7371 + n   - the number of local matrices
7372 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`)
7373 
7374   Level: advanced
7375 
7376   Note:
7377   Frees not only the matrices, but also the array that contains the matrices
7378 
7379 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7380 @*/
7381 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7382 {
7383   Mat mat0;
7384 
7385   PetscFunctionBegin;
7386   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7387   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7388   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7389   PetscAssertPointer(mat, 2);
7390 
7391   mat0 = (*mat)[0];
7392   if (mat0 && mat0->ops->destroysubmatrices) {
7393     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7394   } else {
7395     PetscCall(MatDestroyMatrices(n, mat));
7396   }
7397   PetscFunctionReturn(PETSC_SUCCESS);
7398 }
7399 
7400 /*@
7401   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7402 
7403   Collective
7404 
7405   Input Parameter:
7406 . mat - the matrix
7407 
7408   Output Parameter:
7409 . matstruct - the sequential matrix with the nonzero structure of `mat`
7410 
7411   Level: developer
7412 
7413 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7414 @*/
7415 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7416 {
7417   PetscFunctionBegin;
7418   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7419   PetscAssertPointer(matstruct, 2);
7420 
7421   PetscValidType(mat, 1);
7422   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7423   MatCheckPreallocated(mat, 1);
7424 
7425   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7426   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7427   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7428   PetscFunctionReturn(PETSC_SUCCESS);
7429 }
7430 
7431 /*@C
7432   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7433 
7434   Collective
7435 
7436   Input Parameter:
7437 . mat - the matrix
7438 
7439   Level: advanced
7440 
7441   Note:
7442   This is not needed, one can just call `MatDestroy()`
7443 
7444 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7445 @*/
7446 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7447 {
7448   PetscFunctionBegin;
7449   PetscAssertPointer(mat, 1);
7450   PetscCall(MatDestroy(mat));
7451   PetscFunctionReturn(PETSC_SUCCESS);
7452 }
7453 
7454 /*@
7455   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7456   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   Note:
7473   The computed overlap preserves the matrix block sizes when the blocks are square.
7474   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7475   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7476 
7477 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7478 @*/
7479 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7480 {
7481   PetscInt i, bs, cbs;
7482 
7483   PetscFunctionBegin;
7484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7485   PetscValidType(mat, 1);
7486   PetscValidLogicalCollectiveInt(mat, n, 2);
7487   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7488   if (n) {
7489     PetscAssertPointer(is, 3);
7490     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7491   }
7492   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7493   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7494   MatCheckPreallocated(mat, 1);
7495 
7496   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7497   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7498   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7499   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7500   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7501   if (bs == cbs) {
7502     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7503   }
7504   PetscFunctionReturn(PETSC_SUCCESS);
7505 }
7506 
7507 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7508 
7509 /*@
7510   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7511   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7512   additional overlap.
7513 
7514   Collective
7515 
7516   Input Parameters:
7517 + mat - the matrix
7518 . n   - the number of index sets
7519 . is  - the array of index sets (these index sets will changed during the call)
7520 - ov  - the additional overlap requested
7521 
7522   `   Options Database Key:
7523 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7524 
7525   Level: developer
7526 
7527 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7528 @*/
7529 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7530 {
7531   PetscInt i;
7532 
7533   PetscFunctionBegin;
7534   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7535   PetscValidType(mat, 1);
7536   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7537   if (n) {
7538     PetscAssertPointer(is, 3);
7539     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7540   }
7541   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7542   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7543   MatCheckPreallocated(mat, 1);
7544   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7545   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7546   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7547   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7548   PetscFunctionReturn(PETSC_SUCCESS);
7549 }
7550 
7551 /*@
7552   MatGetBlockSize - Returns the matrix block size.
7553 
7554   Not Collective
7555 
7556   Input Parameter:
7557 . mat - the matrix
7558 
7559   Output Parameter:
7560 . bs - block size
7561 
7562   Level: intermediate
7563 
7564   Notes:
7565   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7566 
7567   If the block size has not been set yet this routine returns 1.
7568 
7569 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7570 @*/
7571 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7572 {
7573   PetscFunctionBegin;
7574   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7575   PetscAssertPointer(bs, 2);
7576   *bs = mat->rmap->bs;
7577   PetscFunctionReturn(PETSC_SUCCESS);
7578 }
7579 
7580 /*@
7581   MatGetBlockSizes - Returns the matrix block row and column sizes.
7582 
7583   Not Collective
7584 
7585   Input Parameter:
7586 . mat - the matrix
7587 
7588   Output Parameters:
7589 + rbs - row block size
7590 - cbs - column block size
7591 
7592   Level: intermediate
7593 
7594   Notes:
7595   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7596   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7597 
7598   If a block size has not been set yet this routine returns 1.
7599 
7600 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7601 @*/
7602 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7603 {
7604   PetscFunctionBegin;
7605   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7606   if (rbs) PetscAssertPointer(rbs, 2);
7607   if (cbs) PetscAssertPointer(cbs, 3);
7608   if (rbs) *rbs = mat->rmap->bs;
7609   if (cbs) *cbs = mat->cmap->bs;
7610   PetscFunctionReturn(PETSC_SUCCESS);
7611 }
7612 
7613 /*@
7614   MatSetBlockSize - Sets the matrix block size.
7615 
7616   Logically Collective
7617 
7618   Input Parameters:
7619 + mat - the matrix
7620 - bs  - block size
7621 
7622   Level: intermediate
7623 
7624   Notes:
7625   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7626   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7627 
7628   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7629   is compatible with the matrix local sizes.
7630 
7631 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7632 @*/
7633 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7634 {
7635   PetscFunctionBegin;
7636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7637   PetscValidLogicalCollectiveInt(mat, bs, 2);
7638   PetscCall(MatSetBlockSizes(mat, bs, bs));
7639   PetscFunctionReturn(PETSC_SUCCESS);
7640 }
7641 
7642 typedef struct {
7643   PetscInt         n;
7644   IS              *is;
7645   Mat             *mat;
7646   PetscObjectState nonzerostate;
7647   Mat              C;
7648 } EnvelopeData;
7649 
7650 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7651 {
7652   EnvelopeData *edata = (EnvelopeData *)*ptr;
7653 
7654   PetscFunctionBegin;
7655   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7656   PetscCall(PetscFree(edata->is));
7657   PetscCall(PetscFree(edata));
7658   PetscFunctionReturn(PETSC_SUCCESS);
7659 }
7660 
7661 /*@
7662   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7663   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7664 
7665   Collective
7666 
7667   Input Parameter:
7668 . mat - the matrix
7669 
7670   Level: intermediate
7671 
7672   Notes:
7673   There can be zeros within the blocks
7674 
7675   The blocks can overlap between processes, including laying on more than two processes
7676 
7677 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7678 @*/
7679 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7680 {
7681   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7682   PetscInt          *diag, *odiag, sc;
7683   VecScatter         scatter;
7684   PetscScalar       *seqv;
7685   const PetscScalar *parv;
7686   const PetscInt    *ia, *ja;
7687   PetscBool          set, flag, done;
7688   Mat                AA = mat, A;
7689   MPI_Comm           comm;
7690   PetscMPIInt        rank, size, tag;
7691   MPI_Status         status;
7692   PetscContainer     container;
7693   EnvelopeData      *edata;
7694   Vec                seq, par;
7695   IS                 isglobal;
7696 
7697   PetscFunctionBegin;
7698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7699   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7700   if (!set || !flag) {
7701     /* TODO: only needs nonzero structure of transpose */
7702     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7703     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7704   }
7705   PetscCall(MatAIJGetLocalMat(AA, &A));
7706   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7707   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7708 
7709   PetscCall(MatGetLocalSize(mat, &n, NULL));
7710   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7711   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7712   PetscCallMPI(MPI_Comm_size(comm, &size));
7713   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7714 
7715   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7716 
7717   if (rank > 0) {
7718     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7719     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7720   }
7721   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7722   for (i = 0; i < n; i++) {
7723     env = PetscMax(env, ja[ia[i + 1] - 1]);
7724     II  = rstart + i;
7725     if (env == II) {
7726       starts[lblocks]  = tbs;
7727       sizes[lblocks++] = 1 + II - tbs;
7728       tbs              = 1 + II;
7729     }
7730   }
7731   if (rank < size - 1) {
7732     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7733     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7734   }
7735 
7736   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7737   if (!set || !flag) PetscCall(MatDestroy(&AA));
7738   PetscCall(MatDestroy(&A));
7739 
7740   PetscCall(PetscNew(&edata));
7741   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7742   edata->n = lblocks;
7743   /* create IS needed for extracting blocks from the original matrix */
7744   PetscCall(PetscMalloc1(lblocks, &edata->is));
7745   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7746 
7747   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7748   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7749   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7750   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7751   PetscCall(MatSetType(edata->C, MATAIJ));
7752 
7753   /* Communicate the start and end of each row, from each block to the correct rank */
7754   /* TODO: Use PetscSF instead of VecScatter */
7755   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7756   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7757   PetscCall(VecGetArrayWrite(seq, &seqv));
7758   for (PetscInt i = 0; i < lblocks; i++) {
7759     for (PetscInt j = 0; j < sizes[i]; j++) {
7760       seqv[cnt]     = starts[i];
7761       seqv[cnt + 1] = starts[i] + sizes[i];
7762       cnt += 2;
7763     }
7764   }
7765   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7766   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7767   sc -= cnt;
7768   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7769   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7770   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7771   PetscCall(ISDestroy(&isglobal));
7772   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7773   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7774   PetscCall(VecScatterDestroy(&scatter));
7775   PetscCall(VecDestroy(&seq));
7776   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7777   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7778   PetscCall(VecGetArrayRead(par, &parv));
7779   cnt = 0;
7780   PetscCall(MatGetSize(mat, NULL, &n));
7781   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7782     PetscInt start, end, d = 0, od = 0;
7783 
7784     start = (PetscInt)PetscRealPart(parv[cnt]);
7785     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7786     cnt += 2;
7787 
7788     if (start < cstart) {
7789       od += cstart - start + n - cend;
7790       d += cend - cstart;
7791     } else if (start < cend) {
7792       od += n - cend;
7793       d += cend - start;
7794     } else od += n - start;
7795     if (end <= cstart) {
7796       od -= cstart - end + n - cend;
7797       d -= cend - cstart;
7798     } else if (end < cend) {
7799       od -= n - cend;
7800       d -= cend - end;
7801     } else od -= n - end;
7802 
7803     odiag[i] = od;
7804     diag[i]  = d;
7805   }
7806   PetscCall(VecRestoreArrayRead(par, &parv));
7807   PetscCall(VecDestroy(&par));
7808   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7809   PetscCall(PetscFree2(diag, odiag));
7810   PetscCall(PetscFree2(sizes, starts));
7811 
7812   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7813   PetscCall(PetscContainerSetPointer(container, edata));
7814   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7815   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7816   PetscCall(PetscObjectDereference((PetscObject)container));
7817   PetscFunctionReturn(PETSC_SUCCESS);
7818 }
7819 
7820 /*@
7821   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7822 
7823   Collective
7824 
7825   Input Parameters:
7826 + A     - the matrix
7827 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7828 
7829   Output Parameter:
7830 . C - matrix with inverted block diagonal of `A`
7831 
7832   Level: advanced
7833 
7834   Note:
7835   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7836 
7837 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7838 @*/
7839 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7840 {
7841   PetscContainer   container;
7842   EnvelopeData    *edata;
7843   PetscObjectState nonzerostate;
7844 
7845   PetscFunctionBegin;
7846   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7847   if (!container) {
7848     PetscCall(MatComputeVariableBlockEnvelope(A));
7849     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7850   }
7851   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7852   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7853   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7854   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7855 
7856   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7857   *C = edata->C;
7858 
7859   for (PetscInt i = 0; i < edata->n; i++) {
7860     Mat          D;
7861     PetscScalar *dvalues;
7862 
7863     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7864     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7865     PetscCall(MatSeqDenseInvert(D));
7866     PetscCall(MatDenseGetArray(D, &dvalues));
7867     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7868     PetscCall(MatDestroy(&D));
7869   }
7870   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7871   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7872   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7873   PetscFunctionReturn(PETSC_SUCCESS);
7874 }
7875 
7876 /*@
7877   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7878 
7879   Not Collective
7880 
7881   Input Parameters:
7882 + mat     - the matrix
7883 . nblocks - the number of blocks on this process, each block can only exist on a single process
7884 - bsizes  - the block sizes
7885 
7886   Level: intermediate
7887 
7888   Notes:
7889   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7890 
7891   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.
7892 
7893 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7894           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7895 @*/
7896 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7897 {
7898   PetscInt ncnt = 0, nlocal;
7899 
7900   PetscFunctionBegin;
7901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7902   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7903   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);
7904   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7905   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);
7906   PetscCall(PetscFree(mat->bsizes));
7907   mat->nblocks = nblocks;
7908   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7909   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7910   PetscFunctionReturn(PETSC_SUCCESS);
7911 }
7912 
7913 /*@C
7914   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7915 
7916   Not Collective; No Fortran Support
7917 
7918   Input Parameter:
7919 . mat - the matrix
7920 
7921   Output Parameters:
7922 + nblocks - the number of blocks on this process
7923 - bsizes  - the block sizes
7924 
7925   Level: intermediate
7926 
7927 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7928 @*/
7929 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7930 {
7931   PetscFunctionBegin;
7932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7933   if (nblocks) *nblocks = mat->nblocks;
7934   if (bsizes) *bsizes = mat->bsizes;
7935   PetscFunctionReturn(PETSC_SUCCESS);
7936 }
7937 
7938 /*@
7939   MatSetBlockSizes - Sets the matrix block row and column sizes.
7940 
7941   Logically Collective
7942 
7943   Input Parameters:
7944 + mat - the matrix
7945 . rbs - row block size
7946 - cbs - column block size
7947 
7948   Level: intermediate
7949 
7950   Notes:
7951   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7952   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7953   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7954 
7955   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7956   are compatible with the matrix local sizes.
7957 
7958   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7959 
7960 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7961 @*/
7962 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7963 {
7964   PetscFunctionBegin;
7965   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7966   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7967   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7968   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7969   if (mat->rmap->refcnt) {
7970     ISLocalToGlobalMapping l2g  = NULL;
7971     PetscLayout            nmap = NULL;
7972 
7973     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7974     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7975     PetscCall(PetscLayoutDestroy(&mat->rmap));
7976     mat->rmap          = nmap;
7977     mat->rmap->mapping = l2g;
7978   }
7979   if (mat->cmap->refcnt) {
7980     ISLocalToGlobalMapping l2g  = NULL;
7981     PetscLayout            nmap = NULL;
7982 
7983     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7984     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7985     PetscCall(PetscLayoutDestroy(&mat->cmap));
7986     mat->cmap          = nmap;
7987     mat->cmap->mapping = l2g;
7988   }
7989   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7990   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7991   PetscFunctionReturn(PETSC_SUCCESS);
7992 }
7993 
7994 /*@
7995   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7996 
7997   Logically Collective
7998 
7999   Input Parameters:
8000 + mat     - the matrix
8001 . fromRow - matrix from which to copy row block size
8002 - fromCol - matrix from which to copy column block size (can be same as fromRow)
8003 
8004   Level: developer
8005 
8006 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
8007 @*/
8008 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8009 {
8010   PetscFunctionBegin;
8011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8012   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8013   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8014   PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8015   PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8016   PetscFunctionReturn(PETSC_SUCCESS);
8017 }
8018 
8019 /*@
8020   MatResidual - Default routine to calculate the residual r = b - Ax
8021 
8022   Collective
8023 
8024   Input Parameters:
8025 + mat - the matrix
8026 . b   - the right-hand-side
8027 - x   - the approximate solution
8028 
8029   Output Parameter:
8030 . r - location to store the residual
8031 
8032   Level: developer
8033 
8034 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8035 @*/
8036 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8037 {
8038   PetscFunctionBegin;
8039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8040   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8041   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8042   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8043   PetscValidType(mat, 1);
8044   MatCheckPreallocated(mat, 1);
8045   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8046   if (!mat->ops->residual) {
8047     PetscCall(MatMult(mat, x, r));
8048     PetscCall(VecAYPX(r, -1.0, b));
8049   } else {
8050     PetscUseTypeMethod(mat, residual, b, x, r);
8051   }
8052   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8053   PetscFunctionReturn(PETSC_SUCCESS);
8054 }
8055 
8056 /*@C
8057   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8058 
8059   Collective
8060 
8061   Input Parameters:
8062 + mat             - the matrix
8063 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8064 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8065 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8066                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8067                  always used.
8068 
8069   Output Parameters:
8070 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8071 . 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
8072 . ja   - the column indices, use `NULL` if not needed
8073 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8074            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8075 
8076   Level: developer
8077 
8078   Notes:
8079   You CANNOT change any of the ia[] or ja[] values.
8080 
8081   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8082 
8083   Fortran Notes:
8084   Use
8085 .vb
8086     PetscInt, pointer :: ia(:),ja(:)
8087     call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8088     ! Access the ith and jth entries via ia(i) and ja(j)
8089 .ve
8090 
8091 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8092 @*/
8093 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8094 {
8095   PetscFunctionBegin;
8096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8097   PetscValidType(mat, 1);
8098   if (n) PetscAssertPointer(n, 5);
8099   if (ia) PetscAssertPointer(ia, 6);
8100   if (ja) PetscAssertPointer(ja, 7);
8101   if (done) PetscAssertPointer(done, 8);
8102   MatCheckPreallocated(mat, 1);
8103   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8104   else {
8105     if (done) *done = PETSC_TRUE;
8106     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8107     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8108     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8109   }
8110   PetscFunctionReturn(PETSC_SUCCESS);
8111 }
8112 
8113 /*@C
8114   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8115 
8116   Collective
8117 
8118   Input Parameters:
8119 + mat             - the matrix
8120 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8121 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8122                 symmetrized
8123 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8124                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8125                  always used.
8126 . n               - number of columns in the (possibly compressed) matrix
8127 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8128 - ja              - the row indices
8129 
8130   Output Parameter:
8131 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8132 
8133   Level: developer
8134 
8135 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8136 @*/
8137 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8138 {
8139   PetscFunctionBegin;
8140   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8141   PetscValidType(mat, 1);
8142   PetscAssertPointer(n, 5);
8143   if (ia) PetscAssertPointer(ia, 6);
8144   if (ja) PetscAssertPointer(ja, 7);
8145   PetscAssertPointer(done, 8);
8146   MatCheckPreallocated(mat, 1);
8147   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8148   else {
8149     *done = PETSC_TRUE;
8150     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8151   }
8152   PetscFunctionReturn(PETSC_SUCCESS);
8153 }
8154 
8155 /*@C
8156   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8157 
8158   Collective
8159 
8160   Input Parameters:
8161 + mat             - the matrix
8162 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8163 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8164 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8165                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8166                     always used.
8167 . n               - size of (possibly compressed) matrix
8168 . ia              - the row pointers
8169 - ja              - the column indices
8170 
8171   Output Parameter:
8172 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8173 
8174   Level: developer
8175 
8176   Note:
8177   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8178   us of the array after it has been restored. If you pass `NULL`, it will
8179   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8180 
8181 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8182 @*/
8183 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8184 {
8185   PetscFunctionBegin;
8186   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8187   PetscValidType(mat, 1);
8188   if (ia) PetscAssertPointer(ia, 6);
8189   if (ja) PetscAssertPointer(ja, 7);
8190   if (done) PetscAssertPointer(done, 8);
8191   MatCheckPreallocated(mat, 1);
8192 
8193   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8194   else {
8195     if (done) *done = PETSC_TRUE;
8196     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8197     if (n) *n = 0;
8198     if (ia) *ia = NULL;
8199     if (ja) *ja = NULL;
8200   }
8201   PetscFunctionReturn(PETSC_SUCCESS);
8202 }
8203 
8204 /*@C
8205   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8206 
8207   Collective
8208 
8209   Input Parameters:
8210 + mat             - the matrix
8211 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8212 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8213 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8214                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8215                     always used.
8216 
8217   Output Parameters:
8218 + n    - size of (possibly compressed) matrix
8219 . ia   - the column pointers
8220 . ja   - the row indices
8221 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8222 
8223   Level: developer
8224 
8225 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8226 @*/
8227 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8228 {
8229   PetscFunctionBegin;
8230   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8231   PetscValidType(mat, 1);
8232   if (ia) PetscAssertPointer(ia, 6);
8233   if (ja) PetscAssertPointer(ja, 7);
8234   PetscAssertPointer(done, 8);
8235   MatCheckPreallocated(mat, 1);
8236 
8237   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8238   else {
8239     *done = PETSC_TRUE;
8240     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8241     if (n) *n = 0;
8242     if (ia) *ia = NULL;
8243     if (ja) *ja = NULL;
8244   }
8245   PetscFunctionReturn(PETSC_SUCCESS);
8246 }
8247 
8248 /*@
8249   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8250   `MatGetColumnIJ()`.
8251 
8252   Collective
8253 
8254   Input Parameters:
8255 + mat        - the matrix
8256 . ncolors    - maximum color value
8257 . n          - number of entries in colorarray
8258 - colorarray - array indicating color for each column
8259 
8260   Output Parameter:
8261 . iscoloring - coloring generated using colorarray information
8262 
8263   Level: developer
8264 
8265 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8266 @*/
8267 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8268 {
8269   PetscFunctionBegin;
8270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8271   PetscValidType(mat, 1);
8272   PetscAssertPointer(colorarray, 4);
8273   PetscAssertPointer(iscoloring, 5);
8274   MatCheckPreallocated(mat, 1);
8275 
8276   if (!mat->ops->coloringpatch) {
8277     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8278   } else {
8279     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8280   }
8281   PetscFunctionReturn(PETSC_SUCCESS);
8282 }
8283 
8284 /*@
8285   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8286 
8287   Logically Collective
8288 
8289   Input Parameter:
8290 . mat - the factored matrix to be reset
8291 
8292   Level: developer
8293 
8294   Notes:
8295   This routine should be used only with factored matrices formed by in-place
8296   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8297   format).  This option can save memory, for example, when solving nonlinear
8298   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8299   ILU(0) preconditioner.
8300 
8301   One can specify in-place ILU(0) factorization by calling
8302 .vb
8303      PCType(pc,PCILU);
8304      PCFactorSeUseInPlace(pc);
8305 .ve
8306   or by using the options -pc_type ilu -pc_factor_in_place
8307 
8308   In-place factorization ILU(0) can also be used as a local
8309   solver for the blocks within the block Jacobi or additive Schwarz
8310   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8311   for details on setting local solver options.
8312 
8313   Most users should employ the `KSP` interface for linear solvers
8314   instead of working directly with matrix algebra routines such as this.
8315   See, e.g., `KSPCreate()`.
8316 
8317 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8318 @*/
8319 PetscErrorCode MatSetUnfactored(Mat mat)
8320 {
8321   PetscFunctionBegin;
8322   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8323   PetscValidType(mat, 1);
8324   MatCheckPreallocated(mat, 1);
8325   mat->factortype = MAT_FACTOR_NONE;
8326   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8327   PetscUseTypeMethod(mat, setunfactored);
8328   PetscFunctionReturn(PETSC_SUCCESS);
8329 }
8330 
8331 /*@
8332   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8333   as the original matrix.
8334 
8335   Collective
8336 
8337   Input Parameters:
8338 + mat   - the original matrix
8339 . isrow - parallel `IS` containing the rows this processor should obtain
8340 . iscol - parallel `IS` containing all columns you wish to keep. Each process should list the columns that will be in IT's "diagonal part" in the new matrix.
8341 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8342 
8343   Output Parameter:
8344 . newmat - the new submatrix, of the same type as the original matrix
8345 
8346   Level: advanced
8347 
8348   Notes:
8349   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8350 
8351   Some matrix types place restrictions on the row and column indices, such
8352   as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8353   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8354 
8355   The index sets may not have duplicate entries.
8356 
8357   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8358   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8359   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8360   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8361   you are finished using it.
8362 
8363   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8364   the input matrix.
8365 
8366   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8367 
8368   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8369   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8370 
8371   Example usage:
8372   Consider the following 8x8 matrix with 34 non-zero values, that is
8373   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8374   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8375   as follows
8376 .vb
8377             1  2  0  |  0  3  0  |  0  4
8378     Proc0   0  5  6  |  7  0  0  |  8  0
8379             9  0 10  | 11  0  0  | 12  0
8380     -------------------------------------
8381            13  0 14  | 15 16 17  |  0  0
8382     Proc1   0 18  0  | 19 20 21  |  0  0
8383             0  0  0  | 22 23  0  | 24  0
8384     -------------------------------------
8385     Proc2  25 26 27  |  0  0 28  | 29  0
8386            30  0  0  | 31 32 33  |  0 34
8387 .ve
8388 
8389   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8390 
8391 .vb
8392             2  0  |  0  3  0  |  0
8393     Proc0   5  6  |  7  0  0  |  8
8394     -------------------------------
8395     Proc1  18  0  | 19 20 21  |  0
8396     -------------------------------
8397     Proc2  26 27  |  0  0 28  | 29
8398             0  0  | 31 32 33  |  0
8399 .ve
8400 
8401 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8402 @*/
8403 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8404 {
8405   PetscMPIInt size;
8406   Mat        *local;
8407   IS          iscoltmp;
8408   PetscBool   flg;
8409 
8410   PetscFunctionBegin;
8411   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8412   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8413   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8414   PetscAssertPointer(newmat, 5);
8415   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8416   PetscValidType(mat, 1);
8417   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8418   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8419 
8420   MatCheckPreallocated(mat, 1);
8421   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8422 
8423   if (!iscol || isrow == iscol) {
8424     PetscBool   stride;
8425     PetscMPIInt grabentirematrix = 0, grab;
8426     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8427     if (stride) {
8428       PetscInt first, step, n, rstart, rend;
8429       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8430       if (step == 1) {
8431         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8432         if (rstart == first) {
8433           PetscCall(ISGetLocalSize(isrow, &n));
8434           if (n == rend - rstart) grabentirematrix = 1;
8435         }
8436       }
8437     }
8438     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8439     if (grab) {
8440       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8441       if (cll == MAT_INITIAL_MATRIX) {
8442         *newmat = mat;
8443         PetscCall(PetscObjectReference((PetscObject)mat));
8444       }
8445       PetscFunctionReturn(PETSC_SUCCESS);
8446     }
8447   }
8448 
8449   if (!iscol) {
8450     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8451   } else {
8452     iscoltmp = iscol;
8453   }
8454 
8455   /* if original matrix is on just one processor then use submatrix generated */
8456   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8457     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8458     goto setproperties;
8459   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8460     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8461     *newmat = *local;
8462     PetscCall(PetscFree(local));
8463     goto setproperties;
8464   } else if (!mat->ops->createsubmatrix) {
8465     /* Create a new matrix type that implements the operation using the full matrix */
8466     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8467     switch (cll) {
8468     case MAT_INITIAL_MATRIX:
8469       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8470       break;
8471     case MAT_REUSE_MATRIX:
8472       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8473       break;
8474     default:
8475       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8476     }
8477     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8478     goto setproperties;
8479   }
8480 
8481   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8482   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8483   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8484 
8485 setproperties:
8486   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8487     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8488     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8489   }
8490   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8491   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8492   PetscFunctionReturn(PETSC_SUCCESS);
8493 }
8494 
8495 /*@
8496   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8497 
8498   Not Collective
8499 
8500   Input Parameters:
8501 + A - the matrix we wish to propagate options from
8502 - B - the matrix we wish to propagate options to
8503 
8504   Level: beginner
8505 
8506   Note:
8507   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8508 
8509 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8510 @*/
8511 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8512 {
8513   PetscFunctionBegin;
8514   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8515   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8516   B->symmetry_eternal            = A->symmetry_eternal;
8517   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8518   B->symmetric                   = A->symmetric;
8519   B->structurally_symmetric      = A->structurally_symmetric;
8520   B->spd                         = A->spd;
8521   B->hermitian                   = A->hermitian;
8522   PetscFunctionReturn(PETSC_SUCCESS);
8523 }
8524 
8525 /*@
8526   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8527   used during the assembly process to store values that belong to
8528   other processors.
8529 
8530   Not Collective
8531 
8532   Input Parameters:
8533 + mat   - the matrix
8534 . size  - the initial size of the stash.
8535 - bsize - the initial size of the block-stash(if used).
8536 
8537   Options Database Keys:
8538 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8539 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8540 
8541   Level: intermediate
8542 
8543   Notes:
8544   The block-stash is used for values set with `MatSetValuesBlocked()` while
8545   the stash is used for values set with `MatSetValues()`
8546 
8547   Run with the option -info and look for output of the form
8548   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8549   to determine the appropriate value, MM, to use for size and
8550   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8551   to determine the value, BMM to use for bsize
8552 
8553 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8554 @*/
8555 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8556 {
8557   PetscFunctionBegin;
8558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8559   PetscValidType(mat, 1);
8560   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8561   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8562   PetscFunctionReturn(PETSC_SUCCESS);
8563 }
8564 
8565 /*@
8566   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8567   the matrix
8568 
8569   Neighbor-wise Collective
8570 
8571   Input Parameters:
8572 + A - the matrix
8573 . x - the vector to be multiplied by the interpolation operator
8574 - y - the vector to be added to the result
8575 
8576   Output Parameter:
8577 . w - the resulting vector
8578 
8579   Level: intermediate
8580 
8581   Notes:
8582   `w` may be the same vector as `y`.
8583 
8584   This allows one to use either the restriction or interpolation (its transpose)
8585   matrix to do the interpolation
8586 
8587 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8588 @*/
8589 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8590 {
8591   PetscInt M, N, Ny;
8592 
8593   PetscFunctionBegin;
8594   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8595   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8596   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8597   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8598   PetscCall(MatGetSize(A, &M, &N));
8599   PetscCall(VecGetSize(y, &Ny));
8600   if (M == Ny) {
8601     PetscCall(MatMultAdd(A, x, y, w));
8602   } else {
8603     PetscCall(MatMultTransposeAdd(A, x, y, w));
8604   }
8605   PetscFunctionReturn(PETSC_SUCCESS);
8606 }
8607 
8608 /*@
8609   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8610   the matrix
8611 
8612   Neighbor-wise Collective
8613 
8614   Input Parameters:
8615 + A - the matrix
8616 - x - the vector to be interpolated
8617 
8618   Output Parameter:
8619 . y - the resulting vector
8620 
8621   Level: intermediate
8622 
8623   Note:
8624   This allows one to use either the restriction or interpolation (its transpose)
8625   matrix to do the interpolation
8626 
8627 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8628 @*/
8629 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8630 {
8631   PetscInt M, N, Ny;
8632 
8633   PetscFunctionBegin;
8634   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8635   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8636   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8637   PetscCall(MatGetSize(A, &M, &N));
8638   PetscCall(VecGetSize(y, &Ny));
8639   if (M == Ny) {
8640     PetscCall(MatMult(A, x, y));
8641   } else {
8642     PetscCall(MatMultTranspose(A, x, y));
8643   }
8644   PetscFunctionReturn(PETSC_SUCCESS);
8645 }
8646 
8647 /*@
8648   MatRestrict - $y = A*x$ or $A^T*x$
8649 
8650   Neighbor-wise Collective
8651 
8652   Input Parameters:
8653 + A - the matrix
8654 - x - the vector to be restricted
8655 
8656   Output Parameter:
8657 . y - the resulting vector
8658 
8659   Level: intermediate
8660 
8661   Note:
8662   This allows one to use either the restriction or interpolation (its transpose)
8663   matrix to do the restriction
8664 
8665 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8666 @*/
8667 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8668 {
8669   PetscInt M, N, Nx;
8670 
8671   PetscFunctionBegin;
8672   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8673   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8674   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8675   PetscCall(MatGetSize(A, &M, &N));
8676   PetscCall(VecGetSize(x, &Nx));
8677   if (M == Nx) {
8678     PetscCall(MatMultTranspose(A, x, y));
8679   } else {
8680     PetscCall(MatMult(A, x, y));
8681   }
8682   PetscFunctionReturn(PETSC_SUCCESS);
8683 }
8684 
8685 /*@
8686   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8687 
8688   Neighbor-wise Collective
8689 
8690   Input Parameters:
8691 + A - the matrix
8692 . x - the input dense matrix to be multiplied
8693 - w - the input dense matrix to be added to the result
8694 
8695   Output Parameter:
8696 . y - the output dense matrix
8697 
8698   Level: intermediate
8699 
8700   Note:
8701   This allows one to use either the restriction or interpolation (its transpose)
8702   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8703   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8704 
8705 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8706 @*/
8707 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8708 {
8709   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8710   PetscBool trans = PETSC_TRUE;
8711   MatReuse  reuse = MAT_INITIAL_MATRIX;
8712 
8713   PetscFunctionBegin;
8714   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8715   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8716   PetscValidType(x, 2);
8717   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8718   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8719   PetscCall(MatGetSize(A, &M, &N));
8720   PetscCall(MatGetSize(x, &Mx, &Nx));
8721   if (N == Mx) trans = PETSC_FALSE;
8722   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);
8723   Mo = trans ? N : M;
8724   if (*y) {
8725     PetscCall(MatGetSize(*y, &My, &Ny));
8726     if (Mo == My && Nx == Ny) {
8727       reuse = MAT_REUSE_MATRIX;
8728     } else {
8729       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);
8730       PetscCall(MatDestroy(y));
8731     }
8732   }
8733 
8734   if (w && *y == w) { /* this is to minimize changes in PCMG */
8735     PetscBool flg;
8736 
8737     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8738     if (w) {
8739       PetscInt My, Ny, Mw, Nw;
8740 
8741       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8742       PetscCall(MatGetSize(*y, &My, &Ny));
8743       PetscCall(MatGetSize(w, &Mw, &Nw));
8744       if (!flg || My != Mw || Ny != Nw) w = NULL;
8745     }
8746     if (!w) {
8747       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8748       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8749       PetscCall(PetscObjectDereference((PetscObject)w));
8750     } else {
8751       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8752     }
8753   }
8754   if (!trans) {
8755     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8756   } else {
8757     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8758   }
8759   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8760   PetscFunctionReturn(PETSC_SUCCESS);
8761 }
8762 
8763 /*@
8764   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8765 
8766   Neighbor-wise Collective
8767 
8768   Input Parameters:
8769 + A - the matrix
8770 - x - the input dense matrix
8771 
8772   Output Parameter:
8773 . y - the output dense matrix
8774 
8775   Level: intermediate
8776 
8777   Note:
8778   This allows one to use either the restriction or interpolation (its transpose)
8779   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8780   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8781 
8782 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8783 @*/
8784 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8785 {
8786   PetscFunctionBegin;
8787   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8788   PetscFunctionReturn(PETSC_SUCCESS);
8789 }
8790 
8791 /*@
8792   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8793 
8794   Neighbor-wise Collective
8795 
8796   Input Parameters:
8797 + A - the matrix
8798 - x - the input dense matrix
8799 
8800   Output Parameter:
8801 . y - the output dense matrix
8802 
8803   Level: intermediate
8804 
8805   Note:
8806   This allows one to use either the restriction or interpolation (its transpose)
8807   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8808   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8809 
8810 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8811 @*/
8812 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8813 {
8814   PetscFunctionBegin;
8815   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8816   PetscFunctionReturn(PETSC_SUCCESS);
8817 }
8818 
8819 /*@
8820   MatGetNullSpace - retrieves the null space of a matrix.
8821 
8822   Logically Collective
8823 
8824   Input Parameters:
8825 + mat    - the matrix
8826 - nullsp - the null space object
8827 
8828   Level: developer
8829 
8830 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8831 @*/
8832 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8833 {
8834   PetscFunctionBegin;
8835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8836   PetscAssertPointer(nullsp, 2);
8837   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8838   PetscFunctionReturn(PETSC_SUCCESS);
8839 }
8840 
8841 /*@C
8842   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8843 
8844   Logically Collective
8845 
8846   Input Parameters:
8847 + n   - the number of matrices
8848 - mat - the array of matrices
8849 
8850   Output Parameters:
8851 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
8852 
8853   Level: developer
8854 
8855   Note:
8856   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8857 
8858 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8859           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8860 @*/
8861 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8862 {
8863   PetscFunctionBegin;
8864   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8865   PetscAssertPointer(mat, 2);
8866   PetscAssertPointer(nullsp, 3);
8867 
8868   PetscCall(PetscCalloc1(3 * n, nullsp));
8869   for (PetscInt i = 0; i < n; i++) {
8870     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8871     (*nullsp)[i] = mat[i]->nullsp;
8872     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8873     (*nullsp)[n + i] = mat[i]->nearnullsp;
8874     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8875     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8876     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8877   }
8878   PetscFunctionReturn(PETSC_SUCCESS);
8879 }
8880 
8881 /*@C
8882   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8883 
8884   Logically Collective
8885 
8886   Input Parameters:
8887 + n      - the number of matrices
8888 . mat    - the array of matrices
8889 - nullsp - an array of null spaces
8890 
8891   Level: developer
8892 
8893   Note:
8894   Call `MatGetNullSpaces()` to create `nullsp`
8895 
8896 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8897           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
8898 @*/
8899 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8900 {
8901   PetscFunctionBegin;
8902   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8903   PetscAssertPointer(mat, 2);
8904   PetscAssertPointer(nullsp, 3);
8905   PetscAssertPointer(*nullsp, 3);
8906 
8907   for (PetscInt i = 0; i < n; i++) {
8908     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8909     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
8910     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
8911     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
8912     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
8913     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
8914     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
8915   }
8916   PetscCall(PetscFree(*nullsp));
8917   PetscFunctionReturn(PETSC_SUCCESS);
8918 }
8919 
8920 /*@
8921   MatSetNullSpace - attaches a null space to a matrix.
8922 
8923   Logically Collective
8924 
8925   Input Parameters:
8926 + mat    - the matrix
8927 - nullsp - the null space object
8928 
8929   Level: advanced
8930 
8931   Notes:
8932   This null space is used by the `KSP` linear solvers to solve singular systems.
8933 
8934   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`
8935 
8936   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
8937   to zero but the linear system will still be solved in a least squares sense.
8938 
8939   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8940   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)$.
8941   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
8942   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
8943   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$).
8944   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8945 
8946   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8947   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8948   routine also automatically calls `MatSetTransposeNullSpace()`.
8949 
8950   The user should call `MatNullSpaceDestroy()`.
8951 
8952 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8953           `KSPSetPCSide()`
8954 @*/
8955 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8956 {
8957   PetscFunctionBegin;
8958   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8959   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8960   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8961   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8962   mat->nullsp = nullsp;
8963   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8964   PetscFunctionReturn(PETSC_SUCCESS);
8965 }
8966 
8967 /*@
8968   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8969 
8970   Logically Collective
8971 
8972   Input Parameters:
8973 + mat    - the matrix
8974 - nullsp - the null space object
8975 
8976   Level: developer
8977 
8978 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8979 @*/
8980 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8981 {
8982   PetscFunctionBegin;
8983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8984   PetscValidType(mat, 1);
8985   PetscAssertPointer(nullsp, 2);
8986   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8987   PetscFunctionReturn(PETSC_SUCCESS);
8988 }
8989 
8990 /*@
8991   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8992 
8993   Logically Collective
8994 
8995   Input Parameters:
8996 + mat    - the matrix
8997 - nullsp - the null space object
8998 
8999   Level: advanced
9000 
9001   Notes:
9002   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9003 
9004   See `MatSetNullSpace()`
9005 
9006 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9007 @*/
9008 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9009 {
9010   PetscFunctionBegin;
9011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9012   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9013   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9014   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9015   mat->transnullsp = nullsp;
9016   PetscFunctionReturn(PETSC_SUCCESS);
9017 }
9018 
9019 /*@
9020   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9021   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9022 
9023   Logically Collective
9024 
9025   Input Parameters:
9026 + mat    - the matrix
9027 - nullsp - the null space object
9028 
9029   Level: advanced
9030 
9031   Notes:
9032   Overwrites any previous near null space that may have been attached
9033 
9034   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9035 
9036 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9037 @*/
9038 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9039 {
9040   PetscFunctionBegin;
9041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9042   PetscValidType(mat, 1);
9043   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9044   MatCheckPreallocated(mat, 1);
9045   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9046   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9047   mat->nearnullsp = nullsp;
9048   PetscFunctionReturn(PETSC_SUCCESS);
9049 }
9050 
9051 /*@
9052   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9053 
9054   Not Collective
9055 
9056   Input Parameter:
9057 . mat - the matrix
9058 
9059   Output Parameter:
9060 . nullsp - the null space object, `NULL` if not set
9061 
9062   Level: advanced
9063 
9064 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9065 @*/
9066 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9067 {
9068   PetscFunctionBegin;
9069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9070   PetscValidType(mat, 1);
9071   PetscAssertPointer(nullsp, 2);
9072   MatCheckPreallocated(mat, 1);
9073   *nullsp = mat->nearnullsp;
9074   PetscFunctionReturn(PETSC_SUCCESS);
9075 }
9076 
9077 /*@
9078   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9079 
9080   Collective
9081 
9082   Input Parameters:
9083 + mat  - the matrix
9084 . row  - row/column permutation
9085 - info - information on desired factorization process
9086 
9087   Level: developer
9088 
9089   Notes:
9090   Probably really in-place only when level of fill is zero, otherwise allocates
9091   new space to store factored matrix and deletes previous memory.
9092 
9093   Most users should employ the `KSP` interface for linear solvers
9094   instead of working directly with matrix algebra routines such as this.
9095   See, e.g., `KSPCreate()`.
9096 
9097   Developer Note:
9098   The Fortran interface is not autogenerated as the
9099   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9100 
9101 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9102 @*/
9103 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9104 {
9105   PetscFunctionBegin;
9106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9107   PetscValidType(mat, 1);
9108   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9109   PetscAssertPointer(info, 3);
9110   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9111   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9112   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9113   MatCheckPreallocated(mat, 1);
9114   PetscUseTypeMethod(mat, iccfactor, row, info);
9115   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9116   PetscFunctionReturn(PETSC_SUCCESS);
9117 }
9118 
9119 /*@
9120   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9121   ghosted ones.
9122 
9123   Not Collective
9124 
9125   Input Parameters:
9126 + mat  - the matrix
9127 - diag - the diagonal values, including ghost ones
9128 
9129   Level: developer
9130 
9131   Notes:
9132   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9133 
9134   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9135 
9136 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9137 @*/
9138 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9139 {
9140   PetscMPIInt size;
9141 
9142   PetscFunctionBegin;
9143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9144   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9145   PetscValidType(mat, 1);
9146 
9147   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9148   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9149   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9150   if (size == 1) {
9151     PetscInt n, m;
9152     PetscCall(VecGetSize(diag, &n));
9153     PetscCall(MatGetSize(mat, NULL, &m));
9154     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9155     PetscCall(MatDiagonalScale(mat, NULL, diag));
9156   } else {
9157     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9158   }
9159   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9160   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9161   PetscFunctionReturn(PETSC_SUCCESS);
9162 }
9163 
9164 /*@
9165   MatGetInertia - Gets the inertia from a factored matrix
9166 
9167   Collective
9168 
9169   Input Parameter:
9170 . mat - the matrix
9171 
9172   Output Parameters:
9173 + nneg  - number of negative eigenvalues
9174 . nzero - number of zero eigenvalues
9175 - npos  - number of positive eigenvalues
9176 
9177   Level: advanced
9178 
9179   Note:
9180   Matrix must have been factored by `MatCholeskyFactor()`
9181 
9182 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9183 @*/
9184 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9185 {
9186   PetscFunctionBegin;
9187   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9188   PetscValidType(mat, 1);
9189   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9190   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9191   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9192   PetscFunctionReturn(PETSC_SUCCESS);
9193 }
9194 
9195 /*@C
9196   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9197 
9198   Neighbor-wise Collective
9199 
9200   Input Parameters:
9201 + mat - the factored matrix obtained with `MatGetFactor()`
9202 - b   - the right-hand-side vectors
9203 
9204   Output Parameter:
9205 . x - the result vectors
9206 
9207   Level: developer
9208 
9209   Note:
9210   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9211   call `MatSolves`(A,x,x).
9212 
9213 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9214 @*/
9215 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9216 {
9217   PetscFunctionBegin;
9218   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9219   PetscValidType(mat, 1);
9220   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9221   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9222   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9223 
9224   MatCheckPreallocated(mat, 1);
9225   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9226   PetscUseTypeMethod(mat, solves, b, x);
9227   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9228   PetscFunctionReturn(PETSC_SUCCESS);
9229 }
9230 
9231 /*@
9232   MatIsSymmetric - Test whether a matrix is symmetric
9233 
9234   Collective
9235 
9236   Input Parameters:
9237 + A   - the matrix to test
9238 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9239 
9240   Output Parameter:
9241 . flg - the result
9242 
9243   Level: intermediate
9244 
9245   Notes:
9246   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9247 
9248   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9249 
9250   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9251   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9252 
9253 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9254           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9255 @*/
9256 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9257 {
9258   PetscFunctionBegin;
9259   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9260   PetscAssertPointer(flg, 3);
9261   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9262   else {
9263     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9264     else PetscCall(MatIsTranspose(A, A, tol, flg));
9265     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9266   }
9267   PetscFunctionReturn(PETSC_SUCCESS);
9268 }
9269 
9270 /*@
9271   MatIsHermitian - Test whether a matrix is Hermitian
9272 
9273   Collective
9274 
9275   Input Parameters:
9276 + A   - the matrix to test
9277 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9278 
9279   Output Parameter:
9280 . flg - the result
9281 
9282   Level: intermediate
9283 
9284   Notes:
9285   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9286 
9287   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9288 
9289   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9290   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9291 
9292 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9293           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9294 @*/
9295 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9296 {
9297   PetscFunctionBegin;
9298   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9299   PetscAssertPointer(flg, 3);
9300   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9301   else {
9302     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9303     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9304     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9305   }
9306   PetscFunctionReturn(PETSC_SUCCESS);
9307 }
9308 
9309 /*@
9310   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9311 
9312   Not Collective
9313 
9314   Input Parameter:
9315 . A - the matrix to check
9316 
9317   Output Parameters:
9318 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9319 - flg - the result (only valid if set is `PETSC_TRUE`)
9320 
9321   Level: advanced
9322 
9323   Notes:
9324   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9325   if you want it explicitly checked
9326 
9327   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9328   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9329 
9330 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9331 @*/
9332 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9333 {
9334   PetscFunctionBegin;
9335   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9336   PetscAssertPointer(set, 2);
9337   PetscAssertPointer(flg, 3);
9338   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9339     *set = PETSC_TRUE;
9340     *flg = PetscBool3ToBool(A->symmetric);
9341   } else {
9342     *set = PETSC_FALSE;
9343   }
9344   PetscFunctionReturn(PETSC_SUCCESS);
9345 }
9346 
9347 /*@
9348   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9349 
9350   Not Collective
9351 
9352   Input Parameter:
9353 . A - the matrix to check
9354 
9355   Output Parameters:
9356 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9357 - flg - the result (only valid if set is `PETSC_TRUE`)
9358 
9359   Level: advanced
9360 
9361   Notes:
9362   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9363 
9364   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9365   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9366 
9367 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9368 @*/
9369 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9370 {
9371   PetscFunctionBegin;
9372   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9373   PetscAssertPointer(set, 2);
9374   PetscAssertPointer(flg, 3);
9375   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9376     *set = PETSC_TRUE;
9377     *flg = PetscBool3ToBool(A->spd);
9378   } else {
9379     *set = PETSC_FALSE;
9380   }
9381   PetscFunctionReturn(PETSC_SUCCESS);
9382 }
9383 
9384 /*@
9385   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9386 
9387   Not Collective
9388 
9389   Input Parameter:
9390 . A - the matrix to check
9391 
9392   Output Parameters:
9393 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9394 - flg - the result (only valid if set is `PETSC_TRUE`)
9395 
9396   Level: advanced
9397 
9398   Notes:
9399   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9400   if you want it explicitly checked
9401 
9402   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9403   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9404 
9405 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9406 @*/
9407 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9408 {
9409   PetscFunctionBegin;
9410   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9411   PetscAssertPointer(set, 2);
9412   PetscAssertPointer(flg, 3);
9413   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9414     *set = PETSC_TRUE;
9415     *flg = PetscBool3ToBool(A->hermitian);
9416   } else {
9417     *set = PETSC_FALSE;
9418   }
9419   PetscFunctionReturn(PETSC_SUCCESS);
9420 }
9421 
9422 /*@
9423   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9424 
9425   Collective
9426 
9427   Input Parameter:
9428 . A - the matrix to test
9429 
9430   Output Parameter:
9431 . flg - the result
9432 
9433   Level: intermediate
9434 
9435   Notes:
9436   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9437 
9438   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
9439   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9440 
9441 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9442 @*/
9443 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9444 {
9445   PetscFunctionBegin;
9446   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9447   PetscAssertPointer(flg, 2);
9448   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9449     *flg = PetscBool3ToBool(A->structurally_symmetric);
9450   } else {
9451     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9452     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9453   }
9454   PetscFunctionReturn(PETSC_SUCCESS);
9455 }
9456 
9457 /*@
9458   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9459 
9460   Not Collective
9461 
9462   Input Parameter:
9463 . A - the matrix to check
9464 
9465   Output Parameters:
9466 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9467 - flg - the result (only valid if set is PETSC_TRUE)
9468 
9469   Level: advanced
9470 
9471   Notes:
9472   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
9473   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9474 
9475   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9476 
9477 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9478 @*/
9479 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9480 {
9481   PetscFunctionBegin;
9482   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9483   PetscAssertPointer(set, 2);
9484   PetscAssertPointer(flg, 3);
9485   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9486     *set = PETSC_TRUE;
9487     *flg = PetscBool3ToBool(A->structurally_symmetric);
9488   } else {
9489     *set = PETSC_FALSE;
9490   }
9491   PetscFunctionReturn(PETSC_SUCCESS);
9492 }
9493 
9494 /*@
9495   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9496   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9497 
9498   Not Collective
9499 
9500   Input Parameter:
9501 . mat - the matrix
9502 
9503   Output Parameters:
9504 + nstash    - the size of the stash
9505 . reallocs  - the number of additional mallocs incurred.
9506 . bnstash   - the size of the block stash
9507 - breallocs - the number of additional mallocs incurred.in the block stash
9508 
9509   Level: advanced
9510 
9511 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9512 @*/
9513 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9514 {
9515   PetscFunctionBegin;
9516   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9517   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9518   PetscFunctionReturn(PETSC_SUCCESS);
9519 }
9520 
9521 /*@
9522   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9523   parallel layout, `PetscLayout` for rows and columns
9524 
9525   Collective
9526 
9527   Input Parameter:
9528 . mat - the matrix
9529 
9530   Output Parameters:
9531 + right - (optional) vector that the matrix can be multiplied against
9532 - left  - (optional) vector that the matrix vector product can be stored in
9533 
9534   Level: advanced
9535 
9536   Notes:
9537   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()`.
9538 
9539   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9540 
9541 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9542 @*/
9543 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9544 {
9545   PetscFunctionBegin;
9546   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9547   PetscValidType(mat, 1);
9548   if (mat->ops->getvecs) {
9549     PetscUseTypeMethod(mat, getvecs, right, left);
9550   } else {
9551     if (right) {
9552       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9553       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9554       PetscCall(VecSetType(*right, mat->defaultvectype));
9555 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9556       if (mat->boundtocpu && mat->bindingpropagates) {
9557         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9558         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9559       }
9560 #endif
9561     }
9562     if (left) {
9563       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9564       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9565       PetscCall(VecSetType(*left, mat->defaultvectype));
9566 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9567       if (mat->boundtocpu && mat->bindingpropagates) {
9568         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9569         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9570       }
9571 #endif
9572     }
9573   }
9574   PetscFunctionReturn(PETSC_SUCCESS);
9575 }
9576 
9577 /*@
9578   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9579   with default values.
9580 
9581   Not Collective
9582 
9583   Input Parameter:
9584 . info - the `MatFactorInfo` data structure
9585 
9586   Level: developer
9587 
9588   Notes:
9589   The solvers are generally used through the `KSP` and `PC` objects, for example
9590   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9591 
9592   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9593 
9594 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9595 @*/
9596 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9597 {
9598   PetscFunctionBegin;
9599   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9600   PetscFunctionReturn(PETSC_SUCCESS);
9601 }
9602 
9603 /*@
9604   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9605 
9606   Collective
9607 
9608   Input Parameters:
9609 + mat - the factored matrix
9610 - is  - the index set defining the Schur indices (0-based)
9611 
9612   Level: advanced
9613 
9614   Notes:
9615   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9616 
9617   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9618 
9619   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9620 
9621 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9622           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9623 @*/
9624 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9625 {
9626   PetscErrorCode (*f)(Mat, IS);
9627 
9628   PetscFunctionBegin;
9629   PetscValidType(mat, 1);
9630   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9631   PetscValidType(is, 2);
9632   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9633   PetscCheckSameComm(mat, 1, is, 2);
9634   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9635   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9636   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9637   PetscCall(MatDestroy(&mat->schur));
9638   PetscCall((*f)(mat, is));
9639   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9640   PetscFunctionReturn(PETSC_SUCCESS);
9641 }
9642 
9643 /*@
9644   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9645 
9646   Logically Collective
9647 
9648   Input Parameters:
9649 + F      - the factored matrix obtained by calling `MatGetFactor()`
9650 . S      - location where to return the Schur complement, can be `NULL`
9651 - status - the status of the Schur complement matrix, can be `NULL`
9652 
9653   Level: advanced
9654 
9655   Notes:
9656   You must call `MatFactorSetSchurIS()` before calling this routine.
9657 
9658   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9659 
9660   The routine provides a copy of the Schur matrix stored within the solver data structures.
9661   The caller must destroy the object when it is no longer needed.
9662   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9663 
9664   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)
9665 
9666   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9667 
9668   Developer Note:
9669   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9670   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9671 
9672 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9673 @*/
9674 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9675 {
9676   PetscFunctionBegin;
9677   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9678   if (S) PetscAssertPointer(S, 2);
9679   if (status) PetscAssertPointer(status, 3);
9680   if (S) {
9681     PetscErrorCode (*f)(Mat, Mat *);
9682 
9683     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9684     if (f) {
9685       PetscCall((*f)(F, S));
9686     } else {
9687       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9688     }
9689   }
9690   if (status) *status = F->schur_status;
9691   PetscFunctionReturn(PETSC_SUCCESS);
9692 }
9693 
9694 /*@
9695   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9696 
9697   Logically Collective
9698 
9699   Input Parameters:
9700 + F      - the factored matrix obtained by calling `MatGetFactor()`
9701 . S      - location where to return the Schur complement, can be `NULL`
9702 - status - the status of the Schur complement matrix, can be `NULL`
9703 
9704   Level: advanced
9705 
9706   Notes:
9707   You must call `MatFactorSetSchurIS()` before calling this routine.
9708 
9709   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9710 
9711   The routine returns a the Schur Complement stored within the data structures of the solver.
9712 
9713   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9714 
9715   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9716 
9717   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9718 
9719   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9720 
9721 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9722 @*/
9723 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9724 {
9725   PetscFunctionBegin;
9726   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9727   if (S) {
9728     PetscAssertPointer(S, 2);
9729     *S = F->schur;
9730   }
9731   if (status) {
9732     PetscAssertPointer(status, 3);
9733     *status = F->schur_status;
9734   }
9735   PetscFunctionReturn(PETSC_SUCCESS);
9736 }
9737 
9738 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9739 {
9740   Mat S = F->schur;
9741 
9742   PetscFunctionBegin;
9743   switch (F->schur_status) {
9744   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9745   case MAT_FACTOR_SCHUR_INVERTED:
9746     if (S) {
9747       S->ops->solve             = NULL;
9748       S->ops->matsolve          = NULL;
9749       S->ops->solvetranspose    = NULL;
9750       S->ops->matsolvetranspose = NULL;
9751       S->ops->solveadd          = NULL;
9752       S->ops->solvetransposeadd = NULL;
9753       S->factortype             = MAT_FACTOR_NONE;
9754       PetscCall(PetscFree(S->solvertype));
9755     }
9756   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9757     break;
9758   default:
9759     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9760   }
9761   PetscFunctionReturn(PETSC_SUCCESS);
9762 }
9763 
9764 /*@
9765   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9766 
9767   Logically Collective
9768 
9769   Input Parameters:
9770 + F      - the factored matrix obtained by calling `MatGetFactor()`
9771 . S      - location where the Schur complement is stored
9772 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9773 
9774   Level: advanced
9775 
9776 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9777 @*/
9778 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9779 {
9780   PetscFunctionBegin;
9781   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9782   if (S) {
9783     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9784     *S = NULL;
9785   }
9786   F->schur_status = status;
9787   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9788   PetscFunctionReturn(PETSC_SUCCESS);
9789 }
9790 
9791 /*@
9792   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9793 
9794   Logically Collective
9795 
9796   Input Parameters:
9797 + F   - the factored matrix obtained by calling `MatGetFactor()`
9798 . rhs - location where the right-hand side of the Schur complement system is stored
9799 - sol - location where the solution of the Schur complement system has to be returned
9800 
9801   Level: advanced
9802 
9803   Notes:
9804   The sizes of the vectors should match the size of the Schur complement
9805 
9806   Must be called after `MatFactorSetSchurIS()`
9807 
9808 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9809 @*/
9810 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9811 {
9812   PetscFunctionBegin;
9813   PetscValidType(F, 1);
9814   PetscValidType(rhs, 2);
9815   PetscValidType(sol, 3);
9816   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9817   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9818   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9819   PetscCheckSameComm(F, 1, rhs, 2);
9820   PetscCheckSameComm(F, 1, sol, 3);
9821   PetscCall(MatFactorFactorizeSchurComplement(F));
9822   switch (F->schur_status) {
9823   case MAT_FACTOR_SCHUR_FACTORED:
9824     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9825     break;
9826   case MAT_FACTOR_SCHUR_INVERTED:
9827     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9828     break;
9829   default:
9830     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9831   }
9832   PetscFunctionReturn(PETSC_SUCCESS);
9833 }
9834 
9835 /*@
9836   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9837 
9838   Logically Collective
9839 
9840   Input Parameters:
9841 + F   - the factored matrix obtained by calling `MatGetFactor()`
9842 . rhs - location where the right-hand side of the Schur complement system is stored
9843 - sol - location where the solution of the Schur complement system has to be returned
9844 
9845   Level: advanced
9846 
9847   Notes:
9848   The sizes of the vectors should match the size of the Schur complement
9849 
9850   Must be called after `MatFactorSetSchurIS()`
9851 
9852 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9853 @*/
9854 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9855 {
9856   PetscFunctionBegin;
9857   PetscValidType(F, 1);
9858   PetscValidType(rhs, 2);
9859   PetscValidType(sol, 3);
9860   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9861   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9862   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9863   PetscCheckSameComm(F, 1, rhs, 2);
9864   PetscCheckSameComm(F, 1, sol, 3);
9865   PetscCall(MatFactorFactorizeSchurComplement(F));
9866   switch (F->schur_status) {
9867   case MAT_FACTOR_SCHUR_FACTORED:
9868     PetscCall(MatSolve(F->schur, rhs, sol));
9869     break;
9870   case MAT_FACTOR_SCHUR_INVERTED:
9871     PetscCall(MatMult(F->schur, rhs, sol));
9872     break;
9873   default:
9874     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9875   }
9876   PetscFunctionReturn(PETSC_SUCCESS);
9877 }
9878 
9879 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9880 #if PetscDefined(HAVE_CUDA)
9881 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9882 #endif
9883 
9884 /* Schur status updated in the interface */
9885 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9886 {
9887   Mat S = F->schur;
9888 
9889   PetscFunctionBegin;
9890   if (S) {
9891     PetscMPIInt size;
9892     PetscBool   isdense, isdensecuda;
9893 
9894     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9895     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9896     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9897     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9898     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9899     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9900     if (isdense) {
9901       PetscCall(MatSeqDenseInvertFactors_Private(S));
9902     } else if (isdensecuda) {
9903 #if defined(PETSC_HAVE_CUDA)
9904       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9905 #endif
9906     }
9907     // HIP??????????????
9908     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9909   }
9910   PetscFunctionReturn(PETSC_SUCCESS);
9911 }
9912 
9913 /*@
9914   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9915 
9916   Logically Collective
9917 
9918   Input Parameter:
9919 . F - the factored matrix obtained by calling `MatGetFactor()`
9920 
9921   Level: advanced
9922 
9923   Notes:
9924   Must be called after `MatFactorSetSchurIS()`.
9925 
9926   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9927 
9928 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9929 @*/
9930 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9931 {
9932   PetscFunctionBegin;
9933   PetscValidType(F, 1);
9934   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9935   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9936   PetscCall(MatFactorFactorizeSchurComplement(F));
9937   PetscCall(MatFactorInvertSchurComplement_Private(F));
9938   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9939   PetscFunctionReturn(PETSC_SUCCESS);
9940 }
9941 
9942 /*@
9943   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9944 
9945   Logically Collective
9946 
9947   Input Parameter:
9948 . F - the factored matrix obtained by calling `MatGetFactor()`
9949 
9950   Level: advanced
9951 
9952   Note:
9953   Must be called after `MatFactorSetSchurIS()`
9954 
9955 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9956 @*/
9957 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9958 {
9959   MatFactorInfo info;
9960 
9961   PetscFunctionBegin;
9962   PetscValidType(F, 1);
9963   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9964   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9965   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9966   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9967   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9968     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9969   } else {
9970     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9971   }
9972   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9973   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9974   PetscFunctionReturn(PETSC_SUCCESS);
9975 }
9976 
9977 /*@
9978   MatPtAP - Creates the matrix product $C = P^T * A * P$
9979 
9980   Neighbor-wise Collective
9981 
9982   Input Parameters:
9983 + A     - the matrix
9984 . P     - the projection matrix
9985 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9986 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
9987           if the result is a dense matrix this is irrelevant
9988 
9989   Output Parameter:
9990 . C - the product matrix
9991 
9992   Level: intermediate
9993 
9994   Notes:
9995   C will be created and must be destroyed by the user with `MatDestroy()`.
9996 
9997   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9998 
9999   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10000 
10001   Developer Note:
10002   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10003 
10004 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10005 @*/
10006 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10007 {
10008   PetscFunctionBegin;
10009   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10010   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10011 
10012   if (scall == MAT_INITIAL_MATRIX) {
10013     PetscCall(MatProductCreate(A, P, NULL, C));
10014     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10015     PetscCall(MatProductSetAlgorithm(*C, "default"));
10016     PetscCall(MatProductSetFill(*C, fill));
10017 
10018     (*C)->product->api_user = PETSC_TRUE;
10019     PetscCall(MatProductSetFromOptions(*C));
10020     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);
10021     PetscCall(MatProductSymbolic(*C));
10022   } else { /* scall == MAT_REUSE_MATRIX */
10023     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10024   }
10025 
10026   PetscCall(MatProductNumeric(*C));
10027   (*C)->symmetric = A->symmetric;
10028   (*C)->spd       = A->spd;
10029   PetscFunctionReturn(PETSC_SUCCESS);
10030 }
10031 
10032 /*@
10033   MatRARt - Creates the matrix product $C = R * A * R^T$
10034 
10035   Neighbor-wise Collective
10036 
10037   Input Parameters:
10038 + A     - the matrix
10039 . R     - the projection matrix
10040 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10041 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10042           if the result is a dense matrix this is irrelevant
10043 
10044   Output Parameter:
10045 . C - the product matrix
10046 
10047   Level: intermediate
10048 
10049   Notes:
10050   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10051 
10052   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10053 
10054   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10055   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10056   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10057   We recommend using `MatPtAP()` when possible.
10058 
10059   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10060 
10061 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10062 @*/
10063 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10064 {
10065   PetscFunctionBegin;
10066   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10067   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10068 
10069   if (scall == MAT_INITIAL_MATRIX) {
10070     PetscCall(MatProductCreate(A, R, NULL, C));
10071     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10072     PetscCall(MatProductSetAlgorithm(*C, "default"));
10073     PetscCall(MatProductSetFill(*C, fill));
10074 
10075     (*C)->product->api_user = PETSC_TRUE;
10076     PetscCall(MatProductSetFromOptions(*C));
10077     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);
10078     PetscCall(MatProductSymbolic(*C));
10079   } else { /* scall == MAT_REUSE_MATRIX */
10080     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10081   }
10082 
10083   PetscCall(MatProductNumeric(*C));
10084   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10085   PetscFunctionReturn(PETSC_SUCCESS);
10086 }
10087 
10088 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10089 {
10090   PetscBool flg = PETSC_TRUE;
10091 
10092   PetscFunctionBegin;
10093   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10094   if (scall == MAT_INITIAL_MATRIX) {
10095     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10096     PetscCall(MatProductCreate(A, B, NULL, C));
10097     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10098     PetscCall(MatProductSetFill(*C, fill));
10099   } else { /* scall == MAT_REUSE_MATRIX */
10100     Mat_Product *product = (*C)->product;
10101 
10102     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10103     if (flg && product && product->type != ptype) {
10104       PetscCall(MatProductClear(*C));
10105       product = NULL;
10106     }
10107     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10108     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10109       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10110       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10111       product        = (*C)->product;
10112       product->fill  = fill;
10113       product->clear = PETSC_TRUE;
10114     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10115       flg = PETSC_FALSE;
10116       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10117     }
10118   }
10119   if (flg) {
10120     (*C)->product->api_user = PETSC_TRUE;
10121     PetscCall(MatProductSetType(*C, ptype));
10122     PetscCall(MatProductSetFromOptions(*C));
10123     PetscCall(MatProductSymbolic(*C));
10124   }
10125   PetscCall(MatProductNumeric(*C));
10126   PetscFunctionReturn(PETSC_SUCCESS);
10127 }
10128 
10129 /*@
10130   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10131 
10132   Neighbor-wise Collective
10133 
10134   Input Parameters:
10135 + A     - the left matrix
10136 . B     - the right matrix
10137 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10138 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10139           if the result is a dense matrix this is irrelevant
10140 
10141   Output Parameter:
10142 . C - the product matrix
10143 
10144   Notes:
10145   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10146 
10147   `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
10148   call to this function with `MAT_INITIAL_MATRIX`.
10149 
10150   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10151 
10152   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`,
10153   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10154 
10155   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10156 
10157   Example of Usage:
10158 .vb
10159      MatProductCreate(A,B,NULL,&C);
10160      MatProductSetType(C,MATPRODUCT_AB);
10161      MatProductSymbolic(C);
10162      MatProductNumeric(C); // compute C=A * B
10163      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10164      MatProductNumeric(C);
10165      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10166      MatProductNumeric(C);
10167 .ve
10168 
10169   Level: intermediate
10170 
10171 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10172 @*/
10173 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10174 {
10175   PetscFunctionBegin;
10176   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10177   PetscFunctionReturn(PETSC_SUCCESS);
10178 }
10179 
10180 /*@
10181   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10182 
10183   Neighbor-wise Collective
10184 
10185   Input Parameters:
10186 + A     - the left matrix
10187 . B     - the right matrix
10188 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10189 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10190 
10191   Output Parameter:
10192 . C - the product matrix
10193 
10194   Options Database Key:
10195 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10196               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10197               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10198 
10199   Level: intermediate
10200 
10201   Notes:
10202   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10203 
10204   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10205 
10206   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10207   actually needed.
10208 
10209   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10210   and for pairs of `MATMPIDENSE` matrices.
10211 
10212   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10213 
10214   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10215 
10216 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10217 @*/
10218 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10219 {
10220   PetscFunctionBegin;
10221   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10222   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10223   PetscFunctionReturn(PETSC_SUCCESS);
10224 }
10225 
10226 /*@
10227   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10228 
10229   Neighbor-wise Collective
10230 
10231   Input Parameters:
10232 + A     - the left matrix
10233 . B     - the right matrix
10234 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10235 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10236 
10237   Output Parameter:
10238 . C - the product matrix
10239 
10240   Level: intermediate
10241 
10242   Notes:
10243   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10244 
10245   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10246 
10247   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10248 
10249   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10250   actually needed.
10251 
10252   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10253   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10254 
10255   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10256 
10257 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10258 @*/
10259 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10260 {
10261   PetscFunctionBegin;
10262   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10263   PetscFunctionReturn(PETSC_SUCCESS);
10264 }
10265 
10266 /*@
10267   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10268 
10269   Neighbor-wise Collective
10270 
10271   Input Parameters:
10272 + A     - the left matrix
10273 . B     - the middle matrix
10274 . C     - the right matrix
10275 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10276 - fill  - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10277           if the result is a dense matrix this is irrelevant
10278 
10279   Output Parameter:
10280 . D - the product matrix
10281 
10282   Level: intermediate
10283 
10284   Notes:
10285   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10286 
10287   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10288 
10289   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10290 
10291   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10292   actually needed.
10293 
10294   If you have many matrices with the same non-zero structure to multiply, you
10295   should use `MAT_REUSE_MATRIX` in all calls but the first
10296 
10297   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10298 
10299 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10300 @*/
10301 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10302 {
10303   PetscFunctionBegin;
10304   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10305   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10306 
10307   if (scall == MAT_INITIAL_MATRIX) {
10308     PetscCall(MatProductCreate(A, B, C, D));
10309     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10310     PetscCall(MatProductSetAlgorithm(*D, "default"));
10311     PetscCall(MatProductSetFill(*D, fill));
10312 
10313     (*D)->product->api_user = PETSC_TRUE;
10314     PetscCall(MatProductSetFromOptions(*D));
10315     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,
10316                ((PetscObject)C)->type_name);
10317     PetscCall(MatProductSymbolic(*D));
10318   } else { /* user may change input matrices when REUSE */
10319     PetscCall(MatProductReplaceMats(A, B, C, *D));
10320   }
10321   PetscCall(MatProductNumeric(*D));
10322   PetscFunctionReturn(PETSC_SUCCESS);
10323 }
10324 
10325 /*@
10326   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10327 
10328   Collective
10329 
10330   Input Parameters:
10331 + mat      - the matrix
10332 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10333 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10334 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10335 
10336   Output Parameter:
10337 . matredundant - redundant matrix
10338 
10339   Level: advanced
10340 
10341   Notes:
10342   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10343   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10344 
10345   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10346   calling it.
10347 
10348   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10349 
10350 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10351 @*/
10352 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10353 {
10354   MPI_Comm       comm;
10355   PetscMPIInt    size;
10356   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10357   Mat_Redundant *redund     = NULL;
10358   PetscSubcomm   psubcomm   = NULL;
10359   MPI_Comm       subcomm_in = subcomm;
10360   Mat           *matseq;
10361   IS             isrow, iscol;
10362   PetscBool      newsubcomm = PETSC_FALSE;
10363 
10364   PetscFunctionBegin;
10365   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10366   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10367     PetscAssertPointer(*matredundant, 5);
10368     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10369   }
10370 
10371   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10372   if (size == 1 || nsubcomm == 1) {
10373     if (reuse == MAT_INITIAL_MATRIX) {
10374       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10375     } else {
10376       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");
10377       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10378     }
10379     PetscFunctionReturn(PETSC_SUCCESS);
10380   }
10381 
10382   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10383   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10384   MatCheckPreallocated(mat, 1);
10385 
10386   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10387   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10388     /* create psubcomm, then get subcomm */
10389     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10390     PetscCallMPI(MPI_Comm_size(comm, &size));
10391     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10392 
10393     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10394     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10395     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10396     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10397     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10398     newsubcomm = PETSC_TRUE;
10399     PetscCall(PetscSubcommDestroy(&psubcomm));
10400   }
10401 
10402   /* get isrow, iscol and a local sequential matrix matseq[0] */
10403   if (reuse == MAT_INITIAL_MATRIX) {
10404     mloc_sub = PETSC_DECIDE;
10405     nloc_sub = PETSC_DECIDE;
10406     if (bs < 1) {
10407       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10408       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10409     } else {
10410       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10411       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10412     }
10413     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10414     rstart = rend - mloc_sub;
10415     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10416     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10417     PetscCall(ISSetIdentity(iscol));
10418   } else { /* reuse == MAT_REUSE_MATRIX */
10419     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");
10420     /* retrieve subcomm */
10421     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10422     redund = (*matredundant)->redundant;
10423     isrow  = redund->isrow;
10424     iscol  = redund->iscol;
10425     matseq = redund->matseq;
10426   }
10427   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10428 
10429   /* get matredundant over subcomm */
10430   if (reuse == MAT_INITIAL_MATRIX) {
10431     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10432 
10433     /* create a supporting struct and attach it to C for reuse */
10434     PetscCall(PetscNew(&redund));
10435     (*matredundant)->redundant = redund;
10436     redund->isrow              = isrow;
10437     redund->iscol              = iscol;
10438     redund->matseq             = matseq;
10439     if (newsubcomm) {
10440       redund->subcomm = subcomm;
10441     } else {
10442       redund->subcomm = MPI_COMM_NULL;
10443     }
10444   } else {
10445     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10446   }
10447 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10448   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10449     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10450     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10451   }
10452 #endif
10453   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10454   PetscFunctionReturn(PETSC_SUCCESS);
10455 }
10456 
10457 /*@C
10458   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10459   a given `Mat`. Each submatrix can span multiple procs.
10460 
10461   Collective
10462 
10463   Input Parameters:
10464 + mat     - the matrix
10465 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10466 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10467 
10468   Output Parameter:
10469 . subMat - parallel sub-matrices each spanning a given `subcomm`
10470 
10471   Level: advanced
10472 
10473   Notes:
10474   The submatrix partition across processors is dictated by `subComm` a
10475   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10476   is not restricted to be grouped with consecutive original MPI processes.
10477 
10478   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10479   map directly to the layout of the original matrix [wrt the local
10480   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10481   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10482   the `subMat`. However the offDiagMat looses some columns - and this is
10483   reconstructed with `MatSetValues()`
10484 
10485   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10486 
10487 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10488 @*/
10489 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10490 {
10491   PetscMPIInt commsize, subCommSize;
10492 
10493   PetscFunctionBegin;
10494   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10495   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10496   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10497 
10498   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");
10499   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10500   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10501   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10502   PetscFunctionReturn(PETSC_SUCCESS);
10503 }
10504 
10505 /*@
10506   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10507 
10508   Not Collective
10509 
10510   Input Parameters:
10511 + mat   - matrix to extract local submatrix from
10512 . isrow - local row indices for submatrix
10513 - iscol - local column indices for submatrix
10514 
10515   Output Parameter:
10516 . submat - the submatrix
10517 
10518   Level: intermediate
10519 
10520   Notes:
10521   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10522 
10523   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10524   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10525 
10526   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10527   `MatSetValuesBlockedLocal()` will also be implemented.
10528 
10529   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10530   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10531 
10532 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10533 @*/
10534 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10535 {
10536   PetscFunctionBegin;
10537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10538   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10539   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10540   PetscCheckSameComm(isrow, 2, iscol, 3);
10541   PetscAssertPointer(submat, 4);
10542   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10543 
10544   if (mat->ops->getlocalsubmatrix) {
10545     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10546   } else {
10547     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10548   }
10549   PetscFunctionReturn(PETSC_SUCCESS);
10550 }
10551 
10552 /*@
10553   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10554 
10555   Not Collective
10556 
10557   Input Parameters:
10558 + mat    - matrix to extract local submatrix from
10559 . isrow  - local row indices for submatrix
10560 . iscol  - local column indices for submatrix
10561 - submat - the submatrix
10562 
10563   Level: intermediate
10564 
10565 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10566 @*/
10567 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10568 {
10569   PetscFunctionBegin;
10570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10571   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10572   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10573   PetscCheckSameComm(isrow, 2, iscol, 3);
10574   PetscAssertPointer(submat, 4);
10575   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10576 
10577   if (mat->ops->restorelocalsubmatrix) {
10578     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10579   } else {
10580     PetscCall(MatDestroy(submat));
10581   }
10582   *submat = NULL;
10583   PetscFunctionReturn(PETSC_SUCCESS);
10584 }
10585 
10586 /*@
10587   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10588 
10589   Collective
10590 
10591   Input Parameter:
10592 . mat - the matrix
10593 
10594   Output Parameter:
10595 . is - if any rows have zero diagonals this contains the list of them
10596 
10597   Level: developer
10598 
10599 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10600 @*/
10601 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10602 {
10603   PetscFunctionBegin;
10604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10605   PetscValidType(mat, 1);
10606   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10607   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10608 
10609   if (!mat->ops->findzerodiagonals) {
10610     Vec                diag;
10611     const PetscScalar *a;
10612     PetscInt          *rows;
10613     PetscInt           rStart, rEnd, r, nrow = 0;
10614 
10615     PetscCall(MatCreateVecs(mat, &diag, NULL));
10616     PetscCall(MatGetDiagonal(mat, diag));
10617     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10618     PetscCall(VecGetArrayRead(diag, &a));
10619     for (r = 0; r < rEnd - rStart; ++r)
10620       if (a[r] == 0.0) ++nrow;
10621     PetscCall(PetscMalloc1(nrow, &rows));
10622     nrow = 0;
10623     for (r = 0; r < rEnd - rStart; ++r)
10624       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10625     PetscCall(VecRestoreArrayRead(diag, &a));
10626     PetscCall(VecDestroy(&diag));
10627     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10628   } else {
10629     PetscUseTypeMethod(mat, findzerodiagonals, is);
10630   }
10631   PetscFunctionReturn(PETSC_SUCCESS);
10632 }
10633 
10634 /*@
10635   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10636 
10637   Collective
10638 
10639   Input Parameter:
10640 . mat - the matrix
10641 
10642   Output Parameter:
10643 . is - contains the list of rows with off block diagonal entries
10644 
10645   Level: developer
10646 
10647 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10648 @*/
10649 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10650 {
10651   PetscFunctionBegin;
10652   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10653   PetscValidType(mat, 1);
10654   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10655   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10656 
10657   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10658   PetscFunctionReturn(PETSC_SUCCESS);
10659 }
10660 
10661 /*@C
10662   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10663 
10664   Collective; No Fortran Support
10665 
10666   Input Parameter:
10667 . mat - the matrix
10668 
10669   Output Parameter:
10670 . values - the block inverses in column major order (FORTRAN-like)
10671 
10672   Level: advanced
10673 
10674   Notes:
10675   The size of the blocks is determined by the block size of the matrix.
10676 
10677   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10678 
10679   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10680 
10681 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10682 @*/
10683 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10684 {
10685   PetscFunctionBegin;
10686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10687   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10688   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10689   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10690   PetscFunctionReturn(PETSC_SUCCESS);
10691 }
10692 
10693 /*@
10694   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10695 
10696   Collective; No Fortran Support
10697 
10698   Input Parameters:
10699 + mat     - the matrix
10700 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10701 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10702 
10703   Output Parameter:
10704 . values - the block inverses in column major order (FORTRAN-like)
10705 
10706   Level: advanced
10707 
10708   Notes:
10709   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10710 
10711   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10712 
10713 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10714 @*/
10715 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10716 {
10717   PetscFunctionBegin;
10718   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10719   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10720   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10721   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10722   PetscFunctionReturn(PETSC_SUCCESS);
10723 }
10724 
10725 /*@
10726   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10727 
10728   Collective
10729 
10730   Input Parameters:
10731 + A - the matrix
10732 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10733 
10734   Level: advanced
10735 
10736   Note:
10737   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10738 
10739 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10740 @*/
10741 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10742 {
10743   const PetscScalar *vals;
10744   PetscInt          *dnnz;
10745   PetscInt           m, rstart, rend, bs, i, j;
10746 
10747   PetscFunctionBegin;
10748   PetscCall(MatInvertBlockDiagonal(A, &vals));
10749   PetscCall(MatGetBlockSize(A, &bs));
10750   PetscCall(MatGetLocalSize(A, &m, NULL));
10751   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10752   PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs));
10753   PetscCall(PetscMalloc1(m / bs, &dnnz));
10754   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10755   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10756   PetscCall(PetscFree(dnnz));
10757   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10758   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10759   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10760   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10761   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10762   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10763   PetscFunctionReturn(PETSC_SUCCESS);
10764 }
10765 
10766 /*@
10767   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10768   via `MatTransposeColoringCreate()`.
10769 
10770   Collective
10771 
10772   Input Parameter:
10773 . c - coloring context
10774 
10775   Level: intermediate
10776 
10777 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10778 @*/
10779 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10780 {
10781   MatTransposeColoring matcolor = *c;
10782 
10783   PetscFunctionBegin;
10784   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10785   if (--((PetscObject)matcolor)->refct > 0) {
10786     matcolor = NULL;
10787     PetscFunctionReturn(PETSC_SUCCESS);
10788   }
10789 
10790   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10791   PetscCall(PetscFree(matcolor->rows));
10792   PetscCall(PetscFree(matcolor->den2sp));
10793   PetscCall(PetscFree(matcolor->colorforcol));
10794   PetscCall(PetscFree(matcolor->columns));
10795   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10796   PetscCall(PetscHeaderDestroy(c));
10797   PetscFunctionReturn(PETSC_SUCCESS);
10798 }
10799 
10800 /*@
10801   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10802   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10803   `MatTransposeColoring` to sparse `B`.
10804 
10805   Collective
10806 
10807   Input Parameters:
10808 + coloring - coloring context created with `MatTransposeColoringCreate()`
10809 - B        - sparse matrix
10810 
10811   Output Parameter:
10812 . Btdense - dense matrix $B^T$
10813 
10814   Level: developer
10815 
10816   Note:
10817   These are used internally for some implementations of `MatRARt()`
10818 
10819 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10820 @*/
10821 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10822 {
10823   PetscFunctionBegin;
10824   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10825   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10826   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10827 
10828   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10829   PetscFunctionReturn(PETSC_SUCCESS);
10830 }
10831 
10832 /*@
10833   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10834   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10835   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10836   $C_{sp}$ from $C_{den}$.
10837 
10838   Collective
10839 
10840   Input Parameters:
10841 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10842 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10843 
10844   Output Parameter:
10845 . Csp - sparse matrix
10846 
10847   Level: developer
10848 
10849   Note:
10850   These are used internally for some implementations of `MatRARt()`
10851 
10852 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10853 @*/
10854 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10855 {
10856   PetscFunctionBegin;
10857   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10858   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10859   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10860 
10861   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10862   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10863   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10864   PetscFunctionReturn(PETSC_SUCCESS);
10865 }
10866 
10867 /*@
10868   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10869 
10870   Collective
10871 
10872   Input Parameters:
10873 + mat        - the matrix product C
10874 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10875 
10876   Output Parameter:
10877 . color - the new coloring context
10878 
10879   Level: intermediate
10880 
10881 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10882           `MatTransColoringApplyDenToSp()`
10883 @*/
10884 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10885 {
10886   MatTransposeColoring c;
10887   MPI_Comm             comm;
10888 
10889   PetscFunctionBegin;
10890   PetscAssertPointer(color, 3);
10891 
10892   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10893   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10894   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10895   c->ctype = iscoloring->ctype;
10896   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10897   *color = c;
10898   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10899   PetscFunctionReturn(PETSC_SUCCESS);
10900 }
10901 
10902 /*@
10903   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10904   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
10905 
10906   Not Collective
10907 
10908   Input Parameter:
10909 . mat - the matrix
10910 
10911   Output Parameter:
10912 . state - the current state
10913 
10914   Level: intermediate
10915 
10916   Notes:
10917   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10918   different matrices
10919 
10920   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10921 
10922   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10923 
10924 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10925 @*/
10926 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10927 {
10928   PetscFunctionBegin;
10929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10930   *state = mat->nonzerostate;
10931   PetscFunctionReturn(PETSC_SUCCESS);
10932 }
10933 
10934 /*@
10935   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10936   matrices from each processor
10937 
10938   Collective
10939 
10940   Input Parameters:
10941 + comm   - the communicators the parallel matrix will live on
10942 . seqmat - the input sequential matrices
10943 . n      - number of local columns (or `PETSC_DECIDE`)
10944 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10945 
10946   Output Parameter:
10947 . mpimat - the parallel matrix generated
10948 
10949   Level: developer
10950 
10951   Note:
10952   The number of columns of the matrix in EACH processor MUST be the same.
10953 
10954 .seealso: [](ch_matrices), `Mat`
10955 @*/
10956 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10957 {
10958   PetscMPIInt size;
10959 
10960   PetscFunctionBegin;
10961   PetscCallMPI(MPI_Comm_size(comm, &size));
10962   if (size == 1) {
10963     if (reuse == MAT_INITIAL_MATRIX) {
10964       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10965     } else {
10966       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10967     }
10968     PetscFunctionReturn(PETSC_SUCCESS);
10969   }
10970 
10971   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");
10972 
10973   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10974   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10975   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10976   PetscFunctionReturn(PETSC_SUCCESS);
10977 }
10978 
10979 /*@
10980   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10981 
10982   Collective
10983 
10984   Input Parameters:
10985 + A - the matrix to create subdomains from
10986 - N - requested number of subdomains
10987 
10988   Output Parameters:
10989 + n   - number of subdomains resulting on this MPI process
10990 - iss - `IS` list with indices of subdomains on this MPI process
10991 
10992   Level: advanced
10993 
10994   Note:
10995   The number of subdomains must be smaller than the communicator size
10996 
10997 .seealso: [](ch_matrices), `Mat`, `IS`
10998 @*/
10999 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11000 {
11001   MPI_Comm    comm, subcomm;
11002   PetscMPIInt size, rank, color;
11003   PetscInt    rstart, rend, k;
11004 
11005   PetscFunctionBegin;
11006   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11007   PetscCallMPI(MPI_Comm_size(comm, &size));
11008   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11009   PetscCheck(N >= 1 && N < size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N);
11010   *n    = 1;
11011   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
11012   color = rank / k;
11013   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11014   PetscCall(PetscMalloc1(1, iss));
11015   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11016   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11017   PetscCallMPI(MPI_Comm_free(&subcomm));
11018   PetscFunctionReturn(PETSC_SUCCESS);
11019 }
11020 
11021 /*@
11022   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11023 
11024   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11025   If they are not the same, uses `MatMatMatMult()`.
11026 
11027   Once the coarse grid problem is constructed, correct for interpolation operators
11028   that are not of full rank, which can legitimately happen in the case of non-nested
11029   geometric multigrid.
11030 
11031   Input Parameters:
11032 + restrct     - restriction operator
11033 . dA          - fine grid matrix
11034 . interpolate - interpolation operator
11035 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11036 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11037 
11038   Output Parameter:
11039 . A - the Galerkin coarse matrix
11040 
11041   Options Database Key:
11042 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11043 
11044   Level: developer
11045 
11046   Note:
11047   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11048 
11049 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11050 @*/
11051 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11052 {
11053   IS  zerorows;
11054   Vec diag;
11055 
11056   PetscFunctionBegin;
11057   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11058   /* Construct the coarse grid matrix */
11059   if (interpolate == restrct) {
11060     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11061   } else {
11062     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11063   }
11064 
11065   /* If the interpolation matrix is not of full rank, A will have zero rows.
11066      This can legitimately happen in the case of non-nested geometric multigrid.
11067      In that event, we set the rows of the matrix to the rows of the identity,
11068      ignoring the equations (as the RHS will also be zero). */
11069 
11070   PetscCall(MatFindZeroRows(*A, &zerorows));
11071 
11072   if (zerorows != NULL) { /* if there are any zero rows */
11073     PetscCall(MatCreateVecs(*A, &diag, NULL));
11074     PetscCall(MatGetDiagonal(*A, diag));
11075     PetscCall(VecISSet(diag, zerorows, 1.0));
11076     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11077     PetscCall(VecDestroy(&diag));
11078     PetscCall(ISDestroy(&zerorows));
11079   }
11080   PetscFunctionReturn(PETSC_SUCCESS);
11081 }
11082 
11083 /*@C
11084   MatSetOperation - Allows user to set a matrix operation for any matrix type
11085 
11086   Logically Collective
11087 
11088   Input Parameters:
11089 + mat - the matrix
11090 . op  - the name of the operation
11091 - f   - the function that provides the operation
11092 
11093   Level: developer
11094 
11095   Example Usage:
11096 .vb
11097   extern PetscErrorCode usermult(Mat, Vec, Vec);
11098 
11099   PetscCall(MatCreateXXX(comm, ..., &A));
11100   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11101 .ve
11102 
11103   Notes:
11104   See the file `include/petscmat.h` for a complete list of matrix
11105   operations, which all have the form MATOP_<OPERATION>, where
11106   <OPERATION> is the name (in all capital letters) of the
11107   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11108 
11109   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11110   sequence as the usual matrix interface routines, since they
11111   are intended to be accessed via the usual matrix interface
11112   routines, e.g.,
11113 .vb
11114   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11115 .ve
11116 
11117   In particular each function MUST return `PETSC_SUCCESS` on success and
11118   nonzero on failure.
11119 
11120   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11121 
11122 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11123 @*/
11124 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11125 {
11126   PetscFunctionBegin;
11127   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11128   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11129   (((void (**)(void))mat->ops)[op]) = f;
11130   PetscFunctionReturn(PETSC_SUCCESS);
11131 }
11132 
11133 /*@C
11134   MatGetOperation - Gets a matrix operation for any matrix type.
11135 
11136   Not Collective
11137 
11138   Input Parameters:
11139 + mat - the matrix
11140 - op  - the name of the operation
11141 
11142   Output Parameter:
11143 . f - the function that provides the operation
11144 
11145   Level: developer
11146 
11147   Example Usage:
11148 .vb
11149   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11150 
11151   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11152 .ve
11153 
11154   Notes:
11155   See the file include/petscmat.h for a complete list of matrix
11156   operations, which all have the form MATOP_<OPERATION>, where
11157   <OPERATION> is the name (in all capital letters) of the
11158   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11159 
11160   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11161 
11162 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11163 @*/
11164 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11165 {
11166   PetscFunctionBegin;
11167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11168   *f = (((void (**)(void))mat->ops)[op]);
11169   PetscFunctionReturn(PETSC_SUCCESS);
11170 }
11171 
11172 /*@
11173   MatHasOperation - Determines whether the given matrix supports the particular operation.
11174 
11175   Not Collective
11176 
11177   Input Parameters:
11178 + mat - the matrix
11179 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11180 
11181   Output Parameter:
11182 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11183 
11184   Level: advanced
11185 
11186   Note:
11187   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11188 
11189 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11190 @*/
11191 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11192 {
11193   PetscFunctionBegin;
11194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11195   PetscAssertPointer(has, 3);
11196   if (mat->ops->hasoperation) {
11197     PetscUseTypeMethod(mat, hasoperation, op, has);
11198   } else {
11199     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11200     else {
11201       *has = PETSC_FALSE;
11202       if (op == MATOP_CREATE_SUBMATRIX) {
11203         PetscMPIInt size;
11204 
11205         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11206         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11207       }
11208     }
11209   }
11210   PetscFunctionReturn(PETSC_SUCCESS);
11211 }
11212 
11213 /*@
11214   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11215 
11216   Collective
11217 
11218   Input Parameter:
11219 . mat - the matrix
11220 
11221   Output Parameter:
11222 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11223 
11224   Level: beginner
11225 
11226 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11227 @*/
11228 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11229 {
11230   PetscFunctionBegin;
11231   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11232   PetscValidType(mat, 1);
11233   PetscAssertPointer(cong, 2);
11234   if (!mat->rmap || !mat->cmap) {
11235     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11236     PetscFunctionReturn(PETSC_SUCCESS);
11237   }
11238   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11239     PetscCall(PetscLayoutSetUp(mat->rmap));
11240     PetscCall(PetscLayoutSetUp(mat->cmap));
11241     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11242     if (*cong) mat->congruentlayouts = 1;
11243     else mat->congruentlayouts = 0;
11244   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11245   PetscFunctionReturn(PETSC_SUCCESS);
11246 }
11247 
11248 PetscErrorCode MatSetInf(Mat A)
11249 {
11250   PetscFunctionBegin;
11251   PetscUseTypeMethod(A, setinf);
11252   PetscFunctionReturn(PETSC_SUCCESS);
11253 }
11254 
11255 /*@
11256   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
11257   and possibly removes small values from the graph structure.
11258 
11259   Collective
11260 
11261   Input Parameters:
11262 + A       - the matrix
11263 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11264 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11265 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11266 . num_idx - size of 'index' array
11267 - index   - array of block indices to use for graph strength of connection weight
11268 
11269   Output Parameter:
11270 . graph - the resulting graph
11271 
11272   Level: advanced
11273 
11274 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11275 @*/
11276 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11277 {
11278   PetscFunctionBegin;
11279   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11280   PetscValidType(A, 1);
11281   PetscValidLogicalCollectiveBool(A, scale, 3);
11282   PetscAssertPointer(graph, 7);
11283   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11284   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11285   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11286   PetscFunctionReturn(PETSC_SUCCESS);
11287 }
11288 
11289 /*@
11290   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11291   meaning the same memory is used for the matrix, and no new memory is allocated.
11292 
11293   Collective
11294 
11295   Input Parameters:
11296 + A    - the matrix
11297 - 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
11298 
11299   Level: intermediate
11300 
11301   Developer Note:
11302   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11303   of the arrays in the data structure are unneeded.
11304 
11305 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11306 @*/
11307 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11308 {
11309   PetscFunctionBegin;
11310   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11311   PetscUseTypeMethod(A, eliminatezeros, keep);
11312   PetscFunctionReturn(PETSC_SUCCESS);
11313 }
11314