xref: /petsc/src/mat/interface/matrix.c (revision b6f515db33ea3628673fe08d569f5d88d953eda2)
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   The calling sequence is
586 .vb
587    MatGetRow(matrix,row,ncols,cols,values,ierr)
588          Mat         matrix (input)
589          PetscInt    row    (input)
590          PetscInt    ncols  (output)
591          PetscInt    cols(maxcols) (output)
592          PetscScalar values(maxcols) output
593 .ve
594   where maxcols >= maximum nonzeros in any row of the matrix.
595 
596 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
597 @*/
598 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
599 {
600   PetscInt incols;
601 
602   PetscFunctionBegin;
603   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
604   PetscValidType(mat, 1);
605   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
606   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
607   MatCheckPreallocated(mat, 1);
608   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);
609   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
610   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
611   if (ncols) *ncols = incols;
612   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
613   PetscFunctionReturn(PETSC_SUCCESS);
614 }
615 
616 /*@
617   MatConjugate - replaces the matrix values with their complex conjugates
618 
619   Logically Collective
620 
621   Input Parameter:
622 . mat - the matrix
623 
624   Level: advanced
625 
626 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
627 @*/
628 PetscErrorCode MatConjugate(Mat mat)
629 {
630   PetscFunctionBegin;
631   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
632   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
633   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
634     PetscUseTypeMethod(mat, conjugate);
635     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
636   }
637   PetscFunctionReturn(PETSC_SUCCESS);
638 }
639 
640 /*@C
641   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
642 
643   Not Collective
644 
645   Input Parameters:
646 + mat   - the matrix
647 . row   - the row to get
648 . ncols - the number of nonzeros
649 . cols  - the columns of the nonzeros
650 - vals  - if nonzero the column values
651 
652   Level: advanced
653 
654   Notes:
655   This routine should be called after you have finished examining the entries.
656 
657   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
658   us of the array after it has been restored. If you pass `NULL`, it will
659   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
660 
661   Fortran Note:
662   `MatRestoreRow()` MUST be called after `MatGetRow()`
663   before another call to `MatGetRow()` can be made.
664 
665 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
666 @*/
667 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
668 {
669   PetscFunctionBegin;
670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
671   if (ncols) PetscAssertPointer(ncols, 3);
672   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
673   PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
674   if (ncols) *ncols = 0;
675   if (cols) *cols = NULL;
676   if (vals) *vals = NULL;
677   PetscFunctionReturn(PETSC_SUCCESS);
678 }
679 
680 /*@
681   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
682   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
683 
684   Not Collective
685 
686   Input Parameter:
687 . mat - the matrix
688 
689   Level: advanced
690 
691   Note:
692   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.
693 
694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   PetscTryTypeMethod(mat, getrowuppertriangular);
705   PetscFunctionReturn(PETSC_SUCCESS);
706 }
707 
708 /*@
709   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
710 
711   Not Collective
712 
713   Input Parameter:
714 . mat - the matrix
715 
716   Level: advanced
717 
718   Note:
719   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
720 
721 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
722 @*/
723 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
724 {
725   PetscFunctionBegin;
726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
727   PetscValidType(mat, 1);
728   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
729   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
730   MatCheckPreallocated(mat, 1);
731   PetscTryTypeMethod(mat, restorerowuppertriangular);
732   PetscFunctionReturn(PETSC_SUCCESS);
733 }
734 
735 /*@
736   MatSetOptionsPrefix - Sets the prefix used for searching for all
737   `Mat` options in the database.
738 
739   Logically Collective
740 
741   Input Parameters:
742 + A      - the matrix
743 - prefix - the prefix to prepend to all option names
744 
745   Level: advanced
746 
747   Notes:
748   A hyphen (-) must NOT be given at the beginning of the prefix name.
749   The first character of all runtime options is AUTOMATICALLY the hyphen.
750 
751   This is NOT used for options for the factorization of the matrix. Normally the
752   prefix is automatically passed in from the PC calling the factorization. To set
753   it directly use  `MatSetOptionsPrefixFactor()`
754 
755 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
756 @*/
757 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
758 {
759   PetscFunctionBegin;
760   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
761   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
762   PetscFunctionReturn(PETSC_SUCCESS);
763 }
764 
765 /*@
766   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
767   for matrices created with `MatGetFactor()`
768 
769   Logically Collective
770 
771   Input Parameters:
772 + A      - the matrix
773 - prefix - the prefix to prepend to all option names for the factored matrix
774 
775   Level: developer
776 
777   Notes:
778   A hyphen (-) must NOT be given at the beginning of the prefix name.
779   The first character of all runtime options is AUTOMATICALLY the hyphen.
780 
781   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
782   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
783 
784 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
785 @*/
786 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
787 {
788   PetscFunctionBegin;
789   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
790   if (prefix) {
791     PetscAssertPointer(prefix, 2);
792     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
793     if (prefix != A->factorprefix) {
794       PetscCall(PetscFree(A->factorprefix));
795       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
796     }
797   } else PetscCall(PetscFree(A->factorprefix));
798   PetscFunctionReturn(PETSC_SUCCESS);
799 }
800 
801 /*@
802   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
803   for matrices created with `MatGetFactor()`
804 
805   Logically Collective
806 
807   Input Parameters:
808 + A      - the matrix
809 - prefix - the prefix to prepend to all option names for the factored matrix
810 
811   Level: developer
812 
813   Notes:
814   A hyphen (-) must NOT be given at the beginning of the prefix name.
815   The first character of all runtime options is AUTOMATICALLY the hyphen.
816 
817   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
818   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
819 
820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
821           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
822           `MatSetOptionsPrefix()`
823 @*/
824 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
825 {
826   size_t len1, len2, new_len;
827 
828   PetscFunctionBegin;
829   PetscValidHeader(A, 1);
830   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
831   if (!A->factorprefix) {
832     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
833     PetscFunctionReturn(PETSC_SUCCESS);
834   }
835   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
836 
837   PetscCall(PetscStrlen(A->factorprefix, &len1));
838   PetscCall(PetscStrlen(prefix, &len2));
839   new_len = len1 + len2 + 1;
840   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
841   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@
846   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
847   matrix options in the database.
848 
849   Logically Collective
850 
851   Input Parameters:
852 + A      - the matrix
853 - prefix - the prefix to prepend to all option names
854 
855   Level: advanced
856 
857   Note:
858   A hyphen (-) must NOT be given at the beginning of the prefix name.
859   The first character of all runtime options is AUTOMATICALLY the hyphen.
860 
861 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
862 @*/
863 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
864 {
865   PetscFunctionBegin;
866   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
867   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
868   PetscFunctionReturn(PETSC_SUCCESS);
869 }
870 
871 /*@
872   MatGetOptionsPrefix - Gets the prefix used for searching for all
873   matrix options in the database.
874 
875   Not Collective
876 
877   Input Parameter:
878 . A - the matrix
879 
880   Output Parameter:
881 . prefix - pointer to the prefix string used
882 
883   Level: advanced
884 
885   Fortran Note:
886   The user should pass in a string `prefix` of
887   sufficient length to hold the prefix.
888 
889 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
890 @*/
891 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
892 {
893   PetscFunctionBegin;
894   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
895   PetscAssertPointer(prefix, 2);
896   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
897   PetscFunctionReturn(PETSC_SUCCESS);
898 }
899 
900 /*@
901   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
902 
903   Not Collective
904 
905   Input Parameter:
906 . A - the matrix
907 
908   Output Parameter:
909 . state - the object state
910 
911   Level: advanced
912 
913   Note:
914   Object state is an integer which gets increased every time
915   the object is changed. By saving and later querying the object state
916   one can determine whether information about the object is still current.
917 
918   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
919 
920 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
921 @*/
922 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
926   PetscAssertPointer(state, 2);
927   PetscCall(PetscObjectStateGet((PetscObject)A, state));
928   PetscFunctionReturn(PETSC_SUCCESS);
929 }
930 
931 /*@
932   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
933 
934   Collective
935 
936   Input Parameter:
937 . A - the matrix
938 
939   Level: beginner
940 
941   Notes:
942   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
943   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
944   makes all of the preallocation space available
945 
946   Current values in the matrix are lost in this call.
947 
948   Currently only supported for  `MATAIJ` matrices.
949 
950 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
951 @*/
952 PetscErrorCode MatResetPreallocation(Mat A)
953 {
954   PetscFunctionBegin;
955   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
956   PetscValidType(A, 1);
957   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
958   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
959   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
960   PetscFunctionReturn(PETSC_SUCCESS);
961 }
962 
963 /*@
964   MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
965 
966   Collective
967 
968   Input Parameter:
969 . A - the matrix
970 
971   Level: intermediate
972 
973   Notes:
974   The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
975 
976   Currently only supported for `MATAIJ` matrices.
977 
978 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
979 @*/
980 PetscErrorCode MatResetHash(Mat A)
981 {
982   PetscFunctionBegin;
983   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
984   PetscValidType(A, 1);
985   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()");
986   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
987   PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
988   /* These flags are used to determine whether certain setups occur */
989   A->was_assembled = PETSC_FALSE;
990   A->assembled     = PETSC_FALSE;
991   /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
992   PetscCall(PetscObjectStateIncrease((PetscObject)A));
993   PetscFunctionReturn(PETSC_SUCCESS);
994 }
995 
996 /*@
997   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
998 
999   Collective
1000 
1001   Input Parameter:
1002 . A - the matrix
1003 
1004   Level: advanced
1005 
1006   Notes:
1007   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
1008   setting values in the matrix.
1009 
1010   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
1011 
1012 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
1013 @*/
1014 PetscErrorCode MatSetUp(Mat A)
1015 {
1016   PetscFunctionBegin;
1017   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1018   if (!((PetscObject)A)->type_name) {
1019     PetscMPIInt size;
1020 
1021     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1022     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
1023   }
1024   if (!A->preallocated) PetscTryTypeMethod(A, setup);
1025   PetscCall(PetscLayoutSetUp(A->rmap));
1026   PetscCall(PetscLayoutSetUp(A->cmap));
1027   A->preallocated = PETSC_TRUE;
1028   PetscFunctionReturn(PETSC_SUCCESS);
1029 }
1030 
1031 #if defined(PETSC_HAVE_SAWS)
1032   #include <petscviewersaws.h>
1033 #endif
1034 
1035 /*
1036    If threadsafety is on extraneous matrices may be printed
1037 
1038    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1039 */
1040 #if !defined(PETSC_HAVE_THREADSAFETY)
1041 static PetscInt insidematview = 0;
1042 #endif
1043 
1044 /*@
1045   MatViewFromOptions - View properties of the matrix based on options set in the options database
1046 
1047   Collective
1048 
1049   Input Parameters:
1050 + A    - the matrix
1051 . obj  - optional additional object that provides the options prefix to use
1052 - name - command line option
1053 
1054   Options Database Key:
1055 . -mat_view [viewertype]:... - the viewer and its options
1056 
1057   Level: intermediate
1058 
1059   Note:
1060 .vb
1061     If no value is provided ascii:stdout is used
1062        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1063                                                   for example ascii::ascii_info prints just the information about the object not all details
1064                                                   unless :append is given filename opens in write mode, overwriting what was already there
1065        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1066        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1067        socket[:port]                             defaults to the standard output port
1068        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1069 .ve
1070 
1071 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1072 @*/
1073 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1074 {
1075   PetscFunctionBegin;
1076   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1077 #if !defined(PETSC_HAVE_THREADSAFETY)
1078   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1079 #endif
1080   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1081   PetscFunctionReturn(PETSC_SUCCESS);
1082 }
1083 
1084 /*@
1085   MatView - display information about a matrix in a variety ways
1086 
1087   Collective on viewer
1088 
1089   Input Parameters:
1090 + mat    - the matrix
1091 - viewer - visualization context
1092 
1093   Options Database Keys:
1094 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1095 . -mat_view ::ascii_info_detail    - Prints more detailed info
1096 . -mat_view                        - Prints matrix in ASCII format
1097 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1098 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1099 . -display <name>                  - Sets display name (default is host)
1100 . -draw_pause <sec>                - Sets number of seconds to pause after display
1101 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1102 . -viewer_socket_machine <machine> - -
1103 . -viewer_socket_port <port>       - -
1104 . -mat_view binary                 - save matrix to file in binary format
1105 - -viewer_binary_filename <name>   - -
1106 
1107   Level: beginner
1108 
1109   Notes:
1110   The available visualization contexts include
1111 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1112 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1113 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1114 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1115 
1116   The user can open alternative visualization contexts with
1117 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1118 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1119 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1120 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1121 
1122   The user can call `PetscViewerPushFormat()` to specify the output
1123   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1124   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1125 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1126 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1127 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1128 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1129 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1130 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1131 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1132 
1133   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1134   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1135 
1136   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1137 
1138   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1139   viewer is used.
1140 
1141   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1142   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1143 
1144   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1145   and then use the following mouse functions.
1146 .vb
1147   left mouse: zoom in
1148   middle mouse: zoom out
1149   right mouse: continue with the simulation
1150 .ve
1151 
1152 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1153           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1154 @*/
1155 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1156 {
1157   PetscInt          rows, cols, rbs, cbs;
1158   PetscBool         isascii, isstring, issaws;
1159   PetscViewerFormat format;
1160   PetscMPIInt       size;
1161 
1162   PetscFunctionBegin;
1163   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1164   PetscValidType(mat, 1);
1165   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1166   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1167 
1168   PetscCall(PetscViewerGetFormat(viewer, &format));
1169   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1170   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1171 
1172 #if !defined(PETSC_HAVE_THREADSAFETY)
1173   insidematview++;
1174 #endif
1175   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1176   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1177   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1178   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");
1179 
1180   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1181   if (isascii) {
1182     if (!mat->preallocated) {
1183       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated 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     if (!mat->assembled) {
1191       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1192 #if !defined(PETSC_HAVE_THREADSAFETY)
1193       insidematview--;
1194 #endif
1195       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1196       PetscFunctionReturn(PETSC_SUCCESS);
1197     }
1198     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1199     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1200       MatNullSpace nullsp, transnullsp;
1201 
1202       PetscCall(PetscViewerASCIIPushTab(viewer));
1203       PetscCall(MatGetSize(mat, &rows, &cols));
1204       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1205       if (rbs != 1 || cbs != 1) {
1206         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" : ""));
1207         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1208       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1209       if (mat->factortype) {
1210         MatSolverType solver;
1211         PetscCall(MatFactorGetSolverType(mat, &solver));
1212         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1213       }
1214       if (mat->ops->getinfo) {
1215         MatInfo info;
1216         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1217         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1218         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1219       }
1220       PetscCall(MatGetNullSpace(mat, &nullsp));
1221       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1222       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1223       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1224       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1225       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1226       PetscCall(PetscViewerASCIIPushTab(viewer));
1227       PetscCall(MatProductView(mat, viewer));
1228       PetscCall(PetscViewerASCIIPopTab(viewer));
1229       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1230         IS tmp;
1231 
1232         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1233         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1234         PetscCall(PetscViewerASCIIPushTab(viewer));
1235         PetscCall(ISView(tmp, viewer));
1236         PetscCall(PetscViewerASCIIPopTab(viewer));
1237         PetscCall(ISDestroy(&tmp));
1238       }
1239     }
1240   } else if (issaws) {
1241 #if defined(PETSC_HAVE_SAWS)
1242     PetscMPIInt rank;
1243 
1244     PetscCall(PetscObjectName((PetscObject)mat));
1245     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1246     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1247 #endif
1248   } else if (isstring) {
1249     const char *type;
1250     PetscCall(MatGetType(mat, &type));
1251     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1252     PetscTryTypeMethod(mat, view, viewer);
1253   }
1254   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1255     PetscCall(PetscViewerASCIIPushTab(viewer));
1256     PetscUseTypeMethod(mat, viewnative, viewer);
1257     PetscCall(PetscViewerASCIIPopTab(viewer));
1258   } else if (mat->ops->view) {
1259     PetscCall(PetscViewerASCIIPushTab(viewer));
1260     PetscUseTypeMethod(mat, view, viewer);
1261     PetscCall(PetscViewerASCIIPopTab(viewer));
1262   }
1263   if (isascii) {
1264     PetscCall(PetscViewerGetFormat(viewer, &format));
1265     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1266   }
1267   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1268 #if !defined(PETSC_HAVE_THREADSAFETY)
1269   insidematview--;
1270 #endif
1271   PetscFunctionReturn(PETSC_SUCCESS);
1272 }
1273 
1274 #if defined(PETSC_USE_DEBUG)
1275   #include <../src/sys/totalview/tv_data_display.h>
1276 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1277 {
1278   TV_add_row("Local rows", "int", &mat->rmap->n);
1279   TV_add_row("Local columns", "int", &mat->cmap->n);
1280   TV_add_row("Global rows", "int", &mat->rmap->N);
1281   TV_add_row("Global columns", "int", &mat->cmap->N);
1282   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1283   return TV_format_OK;
1284 }
1285 #endif
1286 
1287 /*@
1288   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1289   with `MatView()`.  The matrix format is determined from the options database.
1290   Generates a parallel MPI matrix if the communicator has more than one
1291   processor.  The default matrix type is `MATAIJ`.
1292 
1293   Collective
1294 
1295   Input Parameters:
1296 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1297             or some related function before a call to `MatLoad()`
1298 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1299 
1300   Options Database Key:
1301 . -matload_block_size <bs> - set block size
1302 
1303   Level: beginner
1304 
1305   Notes:
1306   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1307   `Mat` before calling this routine if you wish to set it from the options database.
1308 
1309   `MatLoad()` automatically loads into the options database any options
1310   given in the file filename.info where filename is the name of the file
1311   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1312   file will be ignored if you use the -viewer_binary_skip_info option.
1313 
1314   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1315   sets the default matrix type AIJ and sets the local and global sizes.
1316   If type and/or size is already set, then the same are used.
1317 
1318   In parallel, each processor can load a subset of rows (or the
1319   entire matrix).  This routine is especially useful when a large
1320   matrix is stored on disk and only part of it is desired on each
1321   processor.  For example, a parallel solver may access only some of
1322   the rows from each processor.  The algorithm used here reads
1323   relatively small blocks of data rather than reading the entire
1324   matrix and then subsetting it.
1325 
1326   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1327   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1328   or the sequence like
1329 .vb
1330     `PetscViewer` v;
1331     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1332     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1333     `PetscViewerSetFromOptions`(v);
1334     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1335     `PetscViewerFileSetName`(v,"datafile");
1336 .ve
1337   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1338 $ -viewer_type {binary, hdf5}
1339 
1340   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1341   and src/mat/tutorials/ex10.c with the second approach.
1342 
1343   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1344   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1345   Multiple objects, both matrices and vectors, can be stored within the same file.
1346   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1347 
1348   Most users should not need to know the details of the binary storage
1349   format, since `MatLoad()` and `MatView()` completely hide these details.
1350   But for anyone who is interested, the standard binary matrix storage
1351   format is
1352 
1353 .vb
1354     PetscInt    MAT_FILE_CLASSID
1355     PetscInt    number of rows
1356     PetscInt    number of columns
1357     PetscInt    total number of nonzeros
1358     PetscInt    *number nonzeros in each row
1359     PetscInt    *column indices of all nonzeros (starting index is zero)
1360     PetscScalar *values of all nonzeros
1361 .ve
1362   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1363   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
1364   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1365 
1366   PETSc automatically does the byte swapping for
1367   machines that store the bytes reversed. Thus if you write your own binary
1368   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1369   and `PetscBinaryWrite()` to see how this may be done.
1370 
1371   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1372   Each processor's chunk is loaded independently by its owning MPI process.
1373   Multiple objects, both matrices and vectors, can be stored within the same file.
1374   They are looked up by their PetscObject name.
1375 
1376   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1377   by default the same structure and naming of the AIJ arrays and column count
1378   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1379 $    save example.mat A b -v7.3
1380   can be directly read by this routine (see Reference 1 for details).
1381 
1382   Depending on your MATLAB version, this format might be a default,
1383   otherwise you can set it as default in Preferences.
1384 
1385   Unless -nocompression flag is used to save the file in MATLAB,
1386   PETSc must be configured with ZLIB package.
1387 
1388   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1389 
1390   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1391 
1392   Corresponding `MatView()` is not yet implemented.
1393 
1394   The loaded matrix is actually a transpose of the original one in MATLAB,
1395   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1396   With this format, matrix is automatically transposed by PETSc,
1397   unless the matrix is marked as SPD or symmetric
1398   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1399 
1400   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1401 
1402 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1403  @*/
1404 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1405 {
1406   PetscBool flg;
1407 
1408   PetscFunctionBegin;
1409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1410   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1411 
1412   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1413 
1414   flg = PETSC_FALSE;
1415   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1416   if (flg) {
1417     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1418     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1419   }
1420   flg = PETSC_FALSE;
1421   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1422   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1423 
1424   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1425   PetscUseTypeMethod(mat, load, viewer);
1426   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1427   PetscFunctionReturn(PETSC_SUCCESS);
1428 }
1429 
1430 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1431 {
1432   Mat_Redundant *redund = *redundant;
1433 
1434   PetscFunctionBegin;
1435   if (redund) {
1436     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1437       PetscCall(ISDestroy(&redund->isrow));
1438       PetscCall(ISDestroy(&redund->iscol));
1439       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1440     } else {
1441       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1442       PetscCall(PetscFree(redund->sbuf_j));
1443       PetscCall(PetscFree(redund->sbuf_a));
1444       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1445         PetscCall(PetscFree(redund->rbuf_j[i]));
1446         PetscCall(PetscFree(redund->rbuf_a[i]));
1447       }
1448       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1449     }
1450 
1451     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1452     PetscCall(PetscFree(redund));
1453   }
1454   PetscFunctionReturn(PETSC_SUCCESS);
1455 }
1456 
1457 /*@
1458   MatDestroy - Frees space taken by a matrix.
1459 
1460   Collective
1461 
1462   Input Parameter:
1463 . A - the matrix
1464 
1465   Level: beginner
1466 
1467   Developer Note:
1468   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1469   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1470   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1471   if changes are needed here.
1472 
1473 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1474 @*/
1475 PetscErrorCode MatDestroy(Mat *A)
1476 {
1477   PetscFunctionBegin;
1478   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1479   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1480   if (--((PetscObject)*A)->refct > 0) {
1481     *A = NULL;
1482     PetscFunctionReturn(PETSC_SUCCESS);
1483   }
1484 
1485   /* if memory was published with SAWs then destroy it */
1486   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1487   PetscTryTypeMethod(*A, destroy);
1488 
1489   PetscCall(PetscFree((*A)->factorprefix));
1490   PetscCall(PetscFree((*A)->defaultvectype));
1491   PetscCall(PetscFree((*A)->defaultrandtype));
1492   PetscCall(PetscFree((*A)->bsizes));
1493   PetscCall(PetscFree((*A)->solvertype));
1494   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1495   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1496   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1497   PetscCall(MatProductClear(*A));
1498   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1499   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1500   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1501   PetscCall(MatDestroy(&(*A)->schur));
1502   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1503   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1504   PetscCall(PetscHeaderDestroy(A));
1505   PetscFunctionReturn(PETSC_SUCCESS);
1506 }
1507 
1508 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1509 /*@
1510   MatSetValues - Inserts or adds a block of values into a matrix.
1511   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1512   MUST be called after all calls to `MatSetValues()` have been completed.
1513 
1514   Not Collective
1515 
1516   Input Parameters:
1517 + mat  - the matrix
1518 . v    - a logically two-dimensional array of values
1519 . m    - the number of rows
1520 . idxm - the global indices of the rows
1521 . n    - the number of columns
1522 . idxn - the global indices of the columns
1523 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1524 
1525   Level: beginner
1526 
1527   Notes:
1528   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1529 
1530   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1531   options cannot be mixed without intervening calls to the assembly
1532   routines.
1533 
1534   `MatSetValues()` uses 0-based row and column numbers in Fortran
1535   as well as in C.
1536 
1537   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1538   simply ignored. This allows easily inserting element stiffness matrices
1539   with homogeneous Dirichlet boundary conditions that you don't want represented
1540   in the matrix.
1541 
1542   Efficiency Alert:
1543   The routine `MatSetValuesBlocked()` may offer much better efficiency
1544   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1545 
1546   Fortran Notes:
1547   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1548 .vb
1549   MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
1550 .ve
1551 
1552   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1553 
1554   Developer Note:
1555   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1556   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1557 
1558 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1559           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1560 @*/
1561 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1562 {
1563   PetscFunctionBeginHot;
1564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1565   PetscValidType(mat, 1);
1566   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1567   PetscAssertPointer(idxm, 3);
1568   PetscAssertPointer(idxn, 5);
1569   MatCheckPreallocated(mat, 1);
1570 
1571   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1572   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1573 
1574   if (PetscDefined(USE_DEBUG)) {
1575     PetscInt i, j;
1576 
1577     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1578     if (v) {
1579       for (i = 0; i < m; i++) {
1580         for (j = 0; j < n; j++) {
1581           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1582 #if defined(PETSC_USE_COMPLEX)
1583             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]);
1584 #else
1585             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]);
1586 #endif
1587         }
1588       }
1589     }
1590     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);
1591     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);
1592   }
1593 
1594   if (mat->assembled) {
1595     mat->was_assembled = PETSC_TRUE;
1596     mat->assembled     = PETSC_FALSE;
1597   }
1598   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1599   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1600   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1605 /*@
1606   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1607   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1608   MUST be called after all calls to `MatSetValues()` have been completed.
1609 
1610   Not Collective
1611 
1612   Input Parameters:
1613 + mat  - the matrix
1614 . v    - a logically two-dimensional array of values
1615 . ism  - the rows to provide
1616 . isn  - the columns to provide
1617 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1618 
1619   Level: beginner
1620 
1621   Notes:
1622   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1623 
1624   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1625   options cannot be mixed without intervening calls to the assembly
1626   routines.
1627 
1628   `MatSetValues()` uses 0-based row and column numbers in Fortran
1629   as well as in C.
1630 
1631   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1632   simply ignored. This allows easily inserting element stiffness matrices
1633   with homogeneous Dirichlet boundary conditions that you don't want represented
1634   in the matrix.
1635 
1636   Efficiency Alert:
1637   The routine `MatSetValuesBlocked()` may offer much better efficiency
1638   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1639 
1640   This is currently not optimized for any particular `ISType`
1641 
1642   Developer Note:
1643   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1644   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1645 
1646 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1647           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1648 @*/
1649 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1650 {
1651   PetscInt        m, n;
1652   const PetscInt *rows, *cols;
1653 
1654   PetscFunctionBeginHot;
1655   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1656   PetscCall(ISGetIndices(ism, &rows));
1657   PetscCall(ISGetIndices(isn, &cols));
1658   PetscCall(ISGetLocalSize(ism, &m));
1659   PetscCall(ISGetLocalSize(isn, &n));
1660   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1661   PetscCall(ISRestoreIndices(ism, &rows));
1662   PetscCall(ISRestoreIndices(isn, &cols));
1663   PetscFunctionReturn(PETSC_SUCCESS);
1664 }
1665 
1666 /*@
1667   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1668   values into a matrix
1669 
1670   Not Collective
1671 
1672   Input Parameters:
1673 + mat - the matrix
1674 . row - the (block) row to set
1675 - v   - a logically two-dimensional array of values
1676 
1677   Level: intermediate
1678 
1679   Notes:
1680   The values, `v`, are column-oriented (for the block version) and sorted
1681 
1682   All the nonzero values in `row` must be provided
1683 
1684   The matrix must have previously had its column indices set, likely by having been assembled.
1685 
1686   `row` must belong to this MPI process
1687 
1688 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1689           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1690 @*/
1691 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1692 {
1693   PetscInt globalrow;
1694 
1695   PetscFunctionBegin;
1696   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1697   PetscValidType(mat, 1);
1698   PetscAssertPointer(v, 3);
1699   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1700   PetscCall(MatSetValuesRow(mat, globalrow, v));
1701   PetscFunctionReturn(PETSC_SUCCESS);
1702 }
1703 
1704 /*@
1705   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1706   values into a matrix
1707 
1708   Not Collective
1709 
1710   Input Parameters:
1711 + mat - the matrix
1712 . row - the (block) row to set
1713 - 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
1714 
1715   Level: advanced
1716 
1717   Notes:
1718   The values, `v`, are column-oriented for the block version.
1719 
1720   All the nonzeros in `row` must be provided
1721 
1722   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1723 
1724   `row` must belong to this process
1725 
1726 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1727           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1728 @*/
1729 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1730 {
1731   PetscFunctionBeginHot;
1732   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1733   PetscValidType(mat, 1);
1734   MatCheckPreallocated(mat, 1);
1735   PetscAssertPointer(v, 3);
1736   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1737   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1738   mat->insertmode = INSERT_VALUES;
1739 
1740   if (mat->assembled) {
1741     mat->was_assembled = PETSC_TRUE;
1742     mat->assembled     = PETSC_FALSE;
1743   }
1744   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1745   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1746   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1747   PetscFunctionReturn(PETSC_SUCCESS);
1748 }
1749 
1750 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1751 /*@
1752   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1753   Using structured grid indexing
1754 
1755   Not Collective
1756 
1757   Input Parameters:
1758 + mat  - the matrix
1759 . m    - number of rows being entered
1760 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1761 . n    - number of columns being entered
1762 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1763 . v    - a logically two-dimensional array of values
1764 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1765 
1766   Level: beginner
1767 
1768   Notes:
1769   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1770 
1771   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1772   options cannot be mixed without intervening calls to the assembly
1773   routines.
1774 
1775   The grid coordinates are across the entire grid, not just the local portion
1776 
1777   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1778   as well as in C.
1779 
1780   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1781 
1782   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1783   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1784 
1785   The columns and rows in the stencil passed in MUST be contained within the
1786   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1787   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1788   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1789   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1790 
1791   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1792   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1793   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1794   `DM_BOUNDARY_PERIODIC` boundary type.
1795 
1796   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
1797   a single value per point) you can skip filling those indices.
1798 
1799   Inspired by the structured grid interface to the HYPRE package
1800   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1801 
1802   Efficiency Alert:
1803   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1804   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1805 
1806   Fortran Note:
1807   `idxm` and `idxn` should be declared as
1808 $     MatStencil idxm(4,m),idxn(4,n)
1809   and the values inserted using
1810 .vb
1811     idxm(MatStencil_i,1) = i
1812     idxm(MatStencil_j,1) = j
1813     idxm(MatStencil_k,1) = k
1814     idxm(MatStencil_c,1) = c
1815     etc
1816 .ve
1817 
1818 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1819           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1820 @*/
1821 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1822 {
1823   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1824   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1825   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1826 
1827   PetscFunctionBegin;
1828   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1829   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1830   PetscValidType(mat, 1);
1831   PetscAssertPointer(idxm, 3);
1832   PetscAssertPointer(idxn, 5);
1833 
1834   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1835     jdxm = buf;
1836     jdxn = buf + m;
1837   } else {
1838     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1839     jdxm = bufm;
1840     jdxn = bufn;
1841   }
1842   for (i = 0; i < m; i++) {
1843     for (j = 0; j < 3 - sdim; j++) dxm++;
1844     tmp = *dxm++ - starts[0];
1845     for (j = 0; j < dim - 1; j++) {
1846       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1847       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1848     }
1849     if (mat->stencil.noc) dxm++;
1850     jdxm[i] = tmp;
1851   }
1852   for (i = 0; i < n; i++) {
1853     for (j = 0; j < 3 - sdim; j++) dxn++;
1854     tmp = *dxn++ - starts[0];
1855     for (j = 0; j < dim - 1; j++) {
1856       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1857       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1858     }
1859     if (mat->stencil.noc) dxn++;
1860     jdxn[i] = tmp;
1861   }
1862   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1863   PetscCall(PetscFree2(bufm, bufn));
1864   PetscFunctionReturn(PETSC_SUCCESS);
1865 }
1866 
1867 /*@
1868   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1869   Using structured grid indexing
1870 
1871   Not Collective
1872 
1873   Input Parameters:
1874 + mat  - the matrix
1875 . m    - number of rows being entered
1876 . idxm - grid coordinates for matrix rows being entered
1877 . n    - number of columns being entered
1878 . idxn - grid coordinates for matrix columns being entered
1879 . v    - a logically two-dimensional array of values
1880 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1881 
1882   Level: beginner
1883 
1884   Notes:
1885   By default the values, `v`, are row-oriented and unsorted.
1886   See `MatSetOption()` for other options.
1887 
1888   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1889   options cannot be mixed without intervening calls to the assembly
1890   routines.
1891 
1892   The grid coordinates are across the entire grid, not just the local portion
1893 
1894   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1895   as well as in C.
1896 
1897   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1898 
1899   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1900   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1901 
1902   The columns and rows in the stencil passed in MUST be contained within the
1903   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1904   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1905   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1906   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1907 
1908   Negative indices may be passed in idxm and idxn, these rows and columns are
1909   simply ignored. This allows easily inserting element stiffness matrices
1910   with homogeneous Dirichlet boundary conditions that you don't want represented
1911   in the matrix.
1912 
1913   Inspired by the structured grid interface to the HYPRE package
1914   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1915 
1916   Fortran Note:
1917   `idxm` and `idxn` should be declared as
1918 $     MatStencil idxm(4,m),idxn(4,n)
1919   and the values inserted using
1920 .vb
1921     idxm(MatStencil_i,1) = i
1922     idxm(MatStencil_j,1) = j
1923     idxm(MatStencil_k,1) = k
1924    etc
1925 .ve
1926 
1927 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1928           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1929           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1930 @*/
1931 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1932 {
1933   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1934   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1935   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1936 
1937   PetscFunctionBegin;
1938   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1939   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1940   PetscValidType(mat, 1);
1941   PetscAssertPointer(idxm, 3);
1942   PetscAssertPointer(idxn, 5);
1943   PetscAssertPointer(v, 6);
1944 
1945   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1946     jdxm = buf;
1947     jdxn = buf + m;
1948   } else {
1949     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1950     jdxm = bufm;
1951     jdxn = bufn;
1952   }
1953   for (i = 0; i < m; i++) {
1954     for (j = 0; j < 3 - sdim; j++) dxm++;
1955     tmp = *dxm++ - starts[0];
1956     for (j = 0; j < sdim - 1; j++) {
1957       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1958       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1959     }
1960     dxm++;
1961     jdxm[i] = tmp;
1962   }
1963   for (i = 0; i < n; i++) {
1964     for (j = 0; j < 3 - sdim; j++) dxn++;
1965     tmp = *dxn++ - starts[0];
1966     for (j = 0; j < sdim - 1; j++) {
1967       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1968       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1969     }
1970     dxn++;
1971     jdxn[i] = tmp;
1972   }
1973   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1974   PetscCall(PetscFree2(bufm, bufn));
1975   PetscFunctionReturn(PETSC_SUCCESS);
1976 }
1977 
1978 /*@
1979   MatSetStencil - Sets the grid information for setting values into a matrix via
1980   `MatSetValuesStencil()`
1981 
1982   Not Collective
1983 
1984   Input Parameters:
1985 + mat    - the matrix
1986 . dim    - dimension of the grid 1, 2, or 3
1987 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1988 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1989 - dof    - number of degrees of freedom per node
1990 
1991   Level: beginner
1992 
1993   Notes:
1994   Inspired by the structured grid interface to the HYPRE package
1995   (www.llnl.gov/CASC/hyper)
1996 
1997   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1998   user.
1999 
2000 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
2001           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
2002 @*/
2003 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
2004 {
2005   PetscFunctionBegin;
2006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2007   PetscAssertPointer(dims, 3);
2008   PetscAssertPointer(starts, 4);
2009 
2010   mat->stencil.dim = dim + (dof > 1);
2011   for (PetscInt i = 0; i < dim; i++) {
2012     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
2013     mat->stencil.starts[i] = starts[dim - i - 1];
2014   }
2015   mat->stencil.dims[dim]   = dof;
2016   mat->stencil.starts[dim] = 0;
2017   mat->stencil.noc         = (PetscBool)(dof == 1);
2018   PetscFunctionReturn(PETSC_SUCCESS);
2019 }
2020 
2021 /*@
2022   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
2023 
2024   Not Collective
2025 
2026   Input Parameters:
2027 + mat  - the matrix
2028 . v    - a logically two-dimensional array of values
2029 . m    - the number of block rows
2030 . idxm - the global block indices
2031 . n    - the number of block columns
2032 . idxn - the global block indices
2033 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
2034 
2035   Level: intermediate
2036 
2037   Notes:
2038   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
2039   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
2040 
2041   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
2042   NOT the total number of rows/columns; for example, if the block size is 2 and
2043   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
2044   The values in `idxm` would be 1 2; that is the first index for each block divided by
2045   the block size.
2046 
2047   You must call `MatSetBlockSize()` when constructing this matrix (before
2048   preallocating it).
2049 
2050   By default the values, `v`, are row-oriented, so the layout of
2051   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
2052 
2053   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
2054   options cannot be mixed without intervening calls to the assembly
2055   routines.
2056 
2057   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2058   as well as in C.
2059 
2060   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2061   simply ignored. This allows easily inserting element stiffness matrices
2062   with homogeneous Dirichlet boundary conditions that you don't want represented
2063   in the matrix.
2064 
2065   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2066   internal searching must be done to determine where to place the
2067   data in the matrix storage space.  By instead inserting blocks of
2068   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2069   reduced.
2070 
2071   Example:
2072 .vb
2073    Suppose m=n=2 and block size(bs) = 2 The array is
2074 
2075    1  2  | 3  4
2076    5  6  | 7  8
2077    - - - | - - -
2078    9  10 | 11 12
2079    13 14 | 15 16
2080 
2081    v[] should be passed in like
2082    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2083 
2084   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2085    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2086 .ve
2087 
2088   Fortran Notes:
2089   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2090 .vb
2091   MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
2092 .ve
2093 
2094   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2095 
2096 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2097 @*/
2098 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2099 {
2100   PetscFunctionBeginHot;
2101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2102   PetscValidType(mat, 1);
2103   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2104   PetscAssertPointer(idxm, 3);
2105   PetscAssertPointer(idxn, 5);
2106   MatCheckPreallocated(mat, 1);
2107   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2108   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2109   if (PetscDefined(USE_DEBUG)) {
2110     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2111     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2112   }
2113   if (PetscDefined(USE_DEBUG)) {
2114     PetscInt rbs, cbs, M, N, i;
2115     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2116     PetscCall(MatGetSize(mat, &M, &N));
2117     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);
2118     for (i = 0; i < n; i++)
2119       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);
2120   }
2121   if (mat->assembled) {
2122     mat->was_assembled = PETSC_TRUE;
2123     mat->assembled     = PETSC_FALSE;
2124   }
2125   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2126   if (mat->ops->setvaluesblocked) {
2127     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2128   } else {
2129     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2130     PetscInt i, j, bs, cbs;
2131 
2132     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2133     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2134       iidxm = buf;
2135       iidxn = buf + m * bs;
2136     } else {
2137       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2138       iidxm = bufr;
2139       iidxn = bufc;
2140     }
2141     for (i = 0; i < m; i++) {
2142       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2143     }
2144     if (m != n || bs != cbs || idxm != idxn) {
2145       for (i = 0; i < n; i++) {
2146         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2147       }
2148     } else iidxn = iidxm;
2149     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2150     PetscCall(PetscFree2(bufr, bufc));
2151   }
2152   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2153   PetscFunctionReturn(PETSC_SUCCESS);
2154 }
2155 
2156 /*@
2157   MatGetValues - Gets a block of local values from a matrix.
2158 
2159   Not Collective; can only return values that are owned by the give process
2160 
2161   Input Parameters:
2162 + mat  - the matrix
2163 . v    - a logically two-dimensional array for storing the values
2164 . m    - the number of rows
2165 . idxm - the  global indices of the rows
2166 . n    - the number of columns
2167 - idxn - the global indices of the columns
2168 
2169   Level: advanced
2170 
2171   Notes:
2172   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2173   The values, `v`, are then returned in a row-oriented format,
2174   analogous to that used by default in `MatSetValues()`.
2175 
2176   `MatGetValues()` uses 0-based row and column numbers in
2177   Fortran as well as in C.
2178 
2179   `MatGetValues()` requires that the matrix has been assembled
2180   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2181   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2182   without intermediate matrix assembly.
2183 
2184   Negative row or column indices will be ignored and those locations in `v` will be
2185   left unchanged.
2186 
2187   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2188   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2189   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2190 
2191 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2192 @*/
2193 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2194 {
2195   PetscFunctionBegin;
2196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2197   PetscValidType(mat, 1);
2198   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2199   PetscAssertPointer(idxm, 3);
2200   PetscAssertPointer(idxn, 5);
2201   PetscAssertPointer(v, 6);
2202   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2203   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2204   MatCheckPreallocated(mat, 1);
2205 
2206   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2207   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2208   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2209   PetscFunctionReturn(PETSC_SUCCESS);
2210 }
2211 
2212 /*@
2213   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2214   defined previously by `MatSetLocalToGlobalMapping()`
2215 
2216   Not Collective
2217 
2218   Input Parameters:
2219 + mat  - the matrix
2220 . nrow - number of rows
2221 . irow - the row local indices
2222 . ncol - number of columns
2223 - icol - the column local indices
2224 
2225   Output Parameter:
2226 . y - a logically two-dimensional array of values
2227 
2228   Level: advanced
2229 
2230   Notes:
2231   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2232 
2233   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,
2234   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2235   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2236   with `MatSetLocalToGlobalMapping()`.
2237 
2238   Developer Note:
2239   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2240   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2241 
2242 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2243           `MatSetValuesLocal()`, `MatGetValues()`
2244 @*/
2245 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2246 {
2247   PetscFunctionBeginHot;
2248   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2249   PetscValidType(mat, 1);
2250   MatCheckPreallocated(mat, 1);
2251   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2252   PetscAssertPointer(irow, 3);
2253   PetscAssertPointer(icol, 5);
2254   if (PetscDefined(USE_DEBUG)) {
2255     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2256     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2257   }
2258   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2259   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2260   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2261   else {
2262     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2263     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2264       irowm = buf;
2265       icolm = buf + nrow;
2266     } else {
2267       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2268       irowm = bufr;
2269       icolm = bufc;
2270     }
2271     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2272     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2273     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2274     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2275     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2276     PetscCall(PetscFree2(bufr, bufc));
2277   }
2278   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2279   PetscFunctionReturn(PETSC_SUCCESS);
2280 }
2281 
2282 /*@
2283   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2284   the same size. Currently, this can only be called once and creates the given matrix.
2285 
2286   Not Collective
2287 
2288   Input Parameters:
2289 + mat  - the matrix
2290 . nb   - the number of blocks
2291 . bs   - the number of rows (and columns) in each block
2292 . rows - a concatenation of the rows for each block
2293 - v    - a concatenation of logically two-dimensional arrays of values
2294 
2295   Level: advanced
2296 
2297   Notes:
2298   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2299 
2300   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2301 
2302 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2303           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2304 @*/
2305 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2306 {
2307   PetscFunctionBegin;
2308   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2309   PetscValidType(mat, 1);
2310   PetscAssertPointer(rows, 4);
2311   PetscAssertPointer(v, 5);
2312   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2313 
2314   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2315   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2316   else {
2317     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2318   }
2319   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2320   PetscFunctionReturn(PETSC_SUCCESS);
2321 }
2322 
2323 /*@
2324   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2325   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2326   using a local (per-processor) numbering.
2327 
2328   Not Collective
2329 
2330   Input Parameters:
2331 + x        - the matrix
2332 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2333 - cmapping - column mapping
2334 
2335   Level: intermediate
2336 
2337   Note:
2338   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2339 
2340 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2341 @*/
2342 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2343 {
2344   PetscFunctionBegin;
2345   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2346   PetscValidType(x, 1);
2347   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2348   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2349   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2350   else {
2351     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2352     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2353   }
2354   PetscFunctionReturn(PETSC_SUCCESS);
2355 }
2356 
2357 /*@
2358   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2359 
2360   Not Collective
2361 
2362   Input Parameter:
2363 . A - the matrix
2364 
2365   Output Parameters:
2366 + rmapping - row mapping
2367 - cmapping - column mapping
2368 
2369   Level: advanced
2370 
2371 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2372 @*/
2373 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2374 {
2375   PetscFunctionBegin;
2376   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2377   PetscValidType(A, 1);
2378   if (rmapping) {
2379     PetscAssertPointer(rmapping, 2);
2380     *rmapping = A->rmap->mapping;
2381   }
2382   if (cmapping) {
2383     PetscAssertPointer(cmapping, 3);
2384     *cmapping = A->cmap->mapping;
2385   }
2386   PetscFunctionReturn(PETSC_SUCCESS);
2387 }
2388 
2389 /*@
2390   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2391 
2392   Logically Collective
2393 
2394   Input Parameters:
2395 + A    - the matrix
2396 . rmap - row layout
2397 - cmap - column layout
2398 
2399   Level: advanced
2400 
2401   Note:
2402   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2403 
2404 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2405 @*/
2406 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2407 {
2408   PetscFunctionBegin;
2409   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2410   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2411   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2412   PetscFunctionReturn(PETSC_SUCCESS);
2413 }
2414 
2415 /*@
2416   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2417 
2418   Not Collective
2419 
2420   Input Parameter:
2421 . A - the matrix
2422 
2423   Output Parameters:
2424 + rmap - row layout
2425 - cmap - column layout
2426 
2427   Level: advanced
2428 
2429 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2430 @*/
2431 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2432 {
2433   PetscFunctionBegin;
2434   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2435   PetscValidType(A, 1);
2436   if (rmap) {
2437     PetscAssertPointer(rmap, 2);
2438     *rmap = A->rmap;
2439   }
2440   if (cmap) {
2441     PetscAssertPointer(cmap, 3);
2442     *cmap = A->cmap;
2443   }
2444   PetscFunctionReturn(PETSC_SUCCESS);
2445 }
2446 
2447 /*@
2448   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2449   using a local numbering of the rows and columns.
2450 
2451   Not Collective
2452 
2453   Input Parameters:
2454 + mat  - the matrix
2455 . nrow - number of rows
2456 . irow - the row local indices
2457 . ncol - number of columns
2458 . icol - the column local indices
2459 . y    - a logically two-dimensional array of values
2460 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2461 
2462   Level: intermediate
2463 
2464   Notes:
2465   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2466 
2467   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2468   options cannot be mixed without intervening calls to the assembly
2469   routines.
2470 
2471   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2472   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2473 
2474   Fortran Notes:
2475   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2476 .vb
2477   MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2478 .ve
2479 
2480   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2481 
2482   Developer Note:
2483   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2484   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2485 
2486 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2487           `MatGetValuesLocal()`
2488 @*/
2489 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2490 {
2491   PetscFunctionBeginHot;
2492   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2493   PetscValidType(mat, 1);
2494   MatCheckPreallocated(mat, 1);
2495   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2496   PetscAssertPointer(irow, 3);
2497   PetscAssertPointer(icol, 5);
2498   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2499   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2500   if (PetscDefined(USE_DEBUG)) {
2501     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2502     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2503   }
2504 
2505   if (mat->assembled) {
2506     mat->was_assembled = PETSC_TRUE;
2507     mat->assembled     = PETSC_FALSE;
2508   }
2509   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2510   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2511   else {
2512     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2513     const PetscInt *irowm, *icolm;
2514 
2515     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2516       bufr  = buf;
2517       bufc  = buf + nrow;
2518       irowm = bufr;
2519       icolm = bufc;
2520     } else {
2521       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2522       irowm = bufr;
2523       icolm = bufc;
2524     }
2525     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2526     else irowm = irow;
2527     if (mat->cmap->mapping) {
2528       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2529         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2530       } else icolm = irowm;
2531     } else icolm = icol;
2532     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2533     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2534   }
2535   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2536   PetscFunctionReturn(PETSC_SUCCESS);
2537 }
2538 
2539 /*@
2540   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2541   using a local ordering of the nodes a block at a time.
2542 
2543   Not Collective
2544 
2545   Input Parameters:
2546 + mat  - the matrix
2547 . nrow - number of rows
2548 . irow - the row local indices
2549 . ncol - number of columns
2550 . icol - the column local indices
2551 . y    - a logically two-dimensional array of values
2552 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2553 
2554   Level: intermediate
2555 
2556   Notes:
2557   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2558   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2559 
2560   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2561   options cannot be mixed without intervening calls to the assembly
2562   routines.
2563 
2564   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2565   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2566 
2567   Fortran Notes:
2568   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2569 .vb
2570   MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2571 .ve
2572 
2573   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2574 
2575   Developer Note:
2576   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2577   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2578 
2579 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2580           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2581 @*/
2582 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2583 {
2584   PetscFunctionBeginHot;
2585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2586   PetscValidType(mat, 1);
2587   MatCheckPreallocated(mat, 1);
2588   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2589   PetscAssertPointer(irow, 3);
2590   PetscAssertPointer(icol, 5);
2591   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2592   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2593   if (PetscDefined(USE_DEBUG)) {
2594     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2595     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);
2596   }
2597 
2598   if (mat->assembled) {
2599     mat->was_assembled = PETSC_TRUE;
2600     mat->assembled     = PETSC_FALSE;
2601   }
2602   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2603     PetscInt irbs, rbs;
2604     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2605     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2606     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2607   }
2608   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2609     PetscInt icbs, cbs;
2610     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2611     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2612     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2613   }
2614   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2615   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2616   else {
2617     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2618     const PetscInt *irowm, *icolm;
2619 
2620     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2621       bufr  = buf;
2622       bufc  = buf + nrow;
2623       irowm = bufr;
2624       icolm = bufc;
2625     } else {
2626       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2627       irowm = bufr;
2628       icolm = bufc;
2629     }
2630     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2631     else irowm = irow;
2632     if (mat->cmap->mapping) {
2633       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2634         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2635       } else icolm = irowm;
2636     } else icolm = icol;
2637     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2638     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2639   }
2640   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2641   PetscFunctionReturn(PETSC_SUCCESS);
2642 }
2643 
2644 /*@
2645   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2646 
2647   Collective
2648 
2649   Input Parameters:
2650 + mat - the matrix
2651 - x   - the vector to be multiplied
2652 
2653   Output Parameter:
2654 . y - the result
2655 
2656   Level: developer
2657 
2658   Note:
2659   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2660   call `MatMultDiagonalBlock`(A,y,y).
2661 
2662 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2663 @*/
2664 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2665 {
2666   PetscFunctionBegin;
2667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2668   PetscValidType(mat, 1);
2669   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2670   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2671 
2672   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2673   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2674   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2675   MatCheckPreallocated(mat, 1);
2676 
2677   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2678   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2679   PetscFunctionReturn(PETSC_SUCCESS);
2680 }
2681 
2682 /*@
2683   MatMult - Computes the matrix-vector product, $y = Ax$.
2684 
2685   Neighbor-wise Collective
2686 
2687   Input Parameters:
2688 + mat - the matrix
2689 - x   - the vector to be multiplied
2690 
2691   Output Parameter:
2692 . y - the result
2693 
2694   Level: beginner
2695 
2696   Note:
2697   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2698   call `MatMult`(A,y,y).
2699 
2700 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2701 @*/
2702 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2703 {
2704   PetscFunctionBegin;
2705   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2706   PetscValidType(mat, 1);
2707   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2708   VecCheckAssembled(x);
2709   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2710   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2711   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2712   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2713   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);
2714   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);
2715   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);
2716   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);
2717   PetscCall(VecSetErrorIfLocked(y, 3));
2718   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2719   MatCheckPreallocated(mat, 1);
2720 
2721   PetscCall(VecLockReadPush(x));
2722   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2723   PetscUseTypeMethod(mat, mult, x, y);
2724   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2725   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2726   PetscCall(VecLockReadPop(x));
2727   PetscFunctionReturn(PETSC_SUCCESS);
2728 }
2729 
2730 /*@
2731   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2732 
2733   Neighbor-wise Collective
2734 
2735   Input Parameters:
2736 + mat - the matrix
2737 - x   - the vector to be multiplied
2738 
2739   Output Parameter:
2740 . y - the result
2741 
2742   Level: beginner
2743 
2744   Notes:
2745   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2746   call `MatMultTranspose`(A,y,y).
2747 
2748   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2749   use `MatMultHermitianTranspose()`
2750 
2751 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2752 @*/
2753 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2754 {
2755   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2756 
2757   PetscFunctionBegin;
2758   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2759   PetscValidType(mat, 1);
2760   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2761   VecCheckAssembled(x);
2762   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2763 
2764   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2765   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2766   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2767   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);
2768   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);
2769   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);
2770   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);
2771   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2772   MatCheckPreallocated(mat, 1);
2773 
2774   if (!mat->ops->multtranspose) {
2775     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2776     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);
2777   } else op = mat->ops->multtranspose;
2778   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2779   PetscCall(VecLockReadPush(x));
2780   PetscCall((*op)(mat, x, y));
2781   PetscCall(VecLockReadPop(x));
2782   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2783   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2784   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2785   PetscFunctionReturn(PETSC_SUCCESS);
2786 }
2787 
2788 /*@
2789   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2790 
2791   Neighbor-wise Collective
2792 
2793   Input Parameters:
2794 + mat - the matrix
2795 - x   - the vector to be multiplied
2796 
2797   Output Parameter:
2798 . y - the result
2799 
2800   Level: beginner
2801 
2802   Notes:
2803   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2804   call `MatMultHermitianTranspose`(A,y,y).
2805 
2806   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2807 
2808   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2809 
2810 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2811 @*/
2812 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2813 {
2814   PetscFunctionBegin;
2815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2816   PetscValidType(mat, 1);
2817   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2818   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2819 
2820   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2821   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2822   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2823   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);
2824   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);
2825   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);
2826   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);
2827   MatCheckPreallocated(mat, 1);
2828 
2829   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2830 #if defined(PETSC_USE_COMPLEX)
2831   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2832     PetscCall(VecLockReadPush(x));
2833     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2834     else PetscUseTypeMethod(mat, mult, x, y);
2835     PetscCall(VecLockReadPop(x));
2836   } else {
2837     Vec w;
2838     PetscCall(VecDuplicate(x, &w));
2839     PetscCall(VecCopy(x, w));
2840     PetscCall(VecConjugate(w));
2841     PetscCall(MatMultTranspose(mat, w, y));
2842     PetscCall(VecDestroy(&w));
2843     PetscCall(VecConjugate(y));
2844   }
2845   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2846 #else
2847   PetscCall(MatMultTranspose(mat, x, y));
2848 #endif
2849   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2850   PetscFunctionReturn(PETSC_SUCCESS);
2851 }
2852 
2853 /*@
2854   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2855 
2856   Neighbor-wise Collective
2857 
2858   Input Parameters:
2859 + mat - the matrix
2860 . v1  - the vector to be multiplied by `mat`
2861 - v2  - the vector to be added to the result
2862 
2863   Output Parameter:
2864 . v3 - the result
2865 
2866   Level: beginner
2867 
2868   Note:
2869   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2870   call `MatMultAdd`(A,v1,v2,v1).
2871 
2872 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2873 @*/
2874 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2875 {
2876   PetscFunctionBegin;
2877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2878   PetscValidType(mat, 1);
2879   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2880   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2881   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2882 
2883   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2884   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2885   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);
2886   /* 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);
2887      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); */
2888   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);
2889   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);
2890   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2891   MatCheckPreallocated(mat, 1);
2892 
2893   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2894   PetscCall(VecLockReadPush(v1));
2895   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2896   PetscCall(VecLockReadPop(v1));
2897   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2898   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2899   PetscFunctionReturn(PETSC_SUCCESS);
2900 }
2901 
2902 /*@
2903   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2904 
2905   Neighbor-wise Collective
2906 
2907   Input Parameters:
2908 + mat - the matrix
2909 . v1  - the vector to be multiplied by the transpose of the matrix
2910 - v2  - the vector to be added to the result
2911 
2912   Output Parameter:
2913 . v3 - the result
2914 
2915   Level: beginner
2916 
2917   Note:
2918   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2919   call `MatMultTransposeAdd`(A,v1,v2,v1).
2920 
2921 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2922 @*/
2923 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2924 {
2925   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2926 
2927   PetscFunctionBegin;
2928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2929   PetscValidType(mat, 1);
2930   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2931   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2932   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2933 
2934   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2935   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2936   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);
2937   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);
2938   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);
2939   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2940   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2941   MatCheckPreallocated(mat, 1);
2942 
2943   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2944   PetscCall(VecLockReadPush(v1));
2945   PetscCall((*op)(mat, v1, v2, v3));
2946   PetscCall(VecLockReadPop(v1));
2947   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2948   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2949   PetscFunctionReturn(PETSC_SUCCESS);
2950 }
2951 
2952 /*@
2953   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2954 
2955   Neighbor-wise Collective
2956 
2957   Input Parameters:
2958 + mat - the matrix
2959 . v1  - the vector to be multiplied by the Hermitian transpose
2960 - v2  - the vector to be added to the result
2961 
2962   Output Parameter:
2963 . v3 - the result
2964 
2965   Level: beginner
2966 
2967   Note:
2968   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2969   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2970 
2971 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2972 @*/
2973 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2974 {
2975   PetscFunctionBegin;
2976   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2977   PetscValidType(mat, 1);
2978   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2979   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2980   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2981 
2982   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2983   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2984   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2985   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);
2986   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);
2987   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);
2988   MatCheckPreallocated(mat, 1);
2989 
2990   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2991   PetscCall(VecLockReadPush(v1));
2992   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2993   else {
2994     Vec w, z;
2995     PetscCall(VecDuplicate(v1, &w));
2996     PetscCall(VecCopy(v1, w));
2997     PetscCall(VecConjugate(w));
2998     PetscCall(VecDuplicate(v3, &z));
2999     PetscCall(MatMultTranspose(mat, w, z));
3000     PetscCall(VecDestroy(&w));
3001     PetscCall(VecConjugate(z));
3002     if (v2 != v3) {
3003       PetscCall(VecWAXPY(v3, 1.0, v2, z));
3004     } else {
3005       PetscCall(VecAXPY(v3, 1.0, z));
3006     }
3007     PetscCall(VecDestroy(&z));
3008   }
3009   PetscCall(VecLockReadPop(v1));
3010   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
3011   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
3012   PetscFunctionReturn(PETSC_SUCCESS);
3013 }
3014 
3015 /*@
3016   MatGetFactorType - gets the type of factorization a matrix is
3017 
3018   Not Collective
3019 
3020   Input Parameter:
3021 . mat - the matrix
3022 
3023   Output Parameter:
3024 . 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`
3025 
3026   Level: intermediate
3027 
3028 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3029           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3030 @*/
3031 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
3032 {
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   PetscValidType(mat, 1);
3036   PetscAssertPointer(t, 2);
3037   *t = mat->factortype;
3038   PetscFunctionReturn(PETSC_SUCCESS);
3039 }
3040 
3041 /*@
3042   MatSetFactorType - sets the type of factorization a matrix is
3043 
3044   Logically Collective
3045 
3046   Input Parameters:
3047 + mat - the matrix
3048 - 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`
3049 
3050   Level: intermediate
3051 
3052 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3053           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3054 @*/
3055 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3056 {
3057   PetscFunctionBegin;
3058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3059   PetscValidType(mat, 1);
3060   mat->factortype = t;
3061   PetscFunctionReturn(PETSC_SUCCESS);
3062 }
3063 
3064 /*@
3065   MatGetInfo - Returns information about matrix storage (number of
3066   nonzeros, memory, etc.).
3067 
3068   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3069 
3070   Input Parameters:
3071 + mat  - the matrix
3072 - 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)
3073 
3074   Output Parameter:
3075 . info - matrix information context
3076 
3077   Options Database Key:
3078 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3079 
3080   Level: intermediate
3081 
3082   Notes:
3083   The `MatInfo` context contains a variety of matrix data, including
3084   number of nonzeros allocated and used, number of mallocs during
3085   matrix assembly, etc.  Additional information for factored matrices
3086   is provided (such as the fill ratio, number of mallocs during
3087   factorization, etc.).
3088 
3089   Example:
3090   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3091   data within the `MatInfo` context.  For example,
3092 .vb
3093       MatInfo info;
3094       Mat     A;
3095       double  mal, nz_a, nz_u;
3096 
3097       MatGetInfo(A, MAT_LOCAL, &info);
3098       mal  = info.mallocs;
3099       nz_a = info.nz_allocated;
3100 .ve
3101 
3102   Fortran Note:
3103   Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3104   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3105   a complete list of parameter names.
3106 .vb
3107       MatInfo info(MAT_INFO_SIZE)
3108       double  precision mal, nz_a
3109       Mat     A
3110       integer ierr
3111 
3112       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3113       mal = info(MAT_INFO_MALLOCS)
3114       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3115 .ve
3116 
3117 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3118 @*/
3119 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3120 {
3121   PetscFunctionBegin;
3122   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3123   PetscValidType(mat, 1);
3124   PetscAssertPointer(info, 3);
3125   MatCheckPreallocated(mat, 1);
3126   PetscUseTypeMethod(mat, getinfo, flag, info);
3127   PetscFunctionReturn(PETSC_SUCCESS);
3128 }
3129 
3130 /*
3131    This is used by external packages where it is not easy to get the info from the actual
3132    matrix factorization.
3133 */
3134 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3135 {
3136   PetscFunctionBegin;
3137   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3138   PetscFunctionReturn(PETSC_SUCCESS);
3139 }
3140 
3141 /*@
3142   MatLUFactor - Performs in-place LU factorization of matrix.
3143 
3144   Collective
3145 
3146   Input Parameters:
3147 + mat  - the matrix
3148 . row  - row permutation
3149 . col  - column permutation
3150 - info - options for factorization, includes
3151 .vb
3152           fill - expected fill as ratio of original fill.
3153           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3154                    Run with the option -info to determine an optimal value to use
3155 .ve
3156 
3157   Level: developer
3158 
3159   Notes:
3160   Most users should employ the `KSP` interface for linear solvers
3161   instead of working directly with matrix algebra routines such as this.
3162   See, e.g., `KSPCreate()`.
3163 
3164   This changes the state of the matrix to a factored matrix; it cannot be used
3165   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3166 
3167   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3168   when not using `KSP`.
3169 
3170   Developer Note:
3171   The Fortran interface is not autogenerated as the
3172   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3173 
3174 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3175           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3176 @*/
3177 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3178 {
3179   MatFactorInfo tinfo;
3180 
3181   PetscFunctionBegin;
3182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3183   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3184   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3185   if (info) PetscAssertPointer(info, 4);
3186   PetscValidType(mat, 1);
3187   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3188   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3189   MatCheckPreallocated(mat, 1);
3190   if (!info) {
3191     PetscCall(MatFactorInfoInitialize(&tinfo));
3192     info = &tinfo;
3193   }
3194 
3195   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3196   PetscUseTypeMethod(mat, lufactor, row, col, info);
3197   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3198   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3199   PetscFunctionReturn(PETSC_SUCCESS);
3200 }
3201 
3202 /*@
3203   MatILUFactor - Performs in-place ILU factorization of matrix.
3204 
3205   Collective
3206 
3207   Input Parameters:
3208 + mat  - the matrix
3209 . row  - row permutation
3210 . col  - column permutation
3211 - info - structure containing
3212 .vb
3213       levels - number of levels of fill.
3214       expected fill - as ratio of original fill.
3215       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3216                 missing diagonal entries)
3217 .ve
3218 
3219   Level: developer
3220 
3221   Notes:
3222   Most users should employ the `KSP` interface for linear solvers
3223   instead of working directly with matrix algebra routines such as this.
3224   See, e.g., `KSPCreate()`.
3225 
3226   Probably really in-place only when level of fill is zero, otherwise allocates
3227   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3228   when not using `KSP`.
3229 
3230   Developer Note:
3231   The Fortran interface is not autogenerated as the
3232   interface definition cannot be generated correctly [due to MatFactorInfo]
3233 
3234 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3235 @*/
3236 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3237 {
3238   PetscFunctionBegin;
3239   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3240   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3241   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3242   PetscAssertPointer(info, 4);
3243   PetscValidType(mat, 1);
3244   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3245   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3246   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3247   MatCheckPreallocated(mat, 1);
3248 
3249   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3250   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3251   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3252   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3253   PetscFunctionReturn(PETSC_SUCCESS);
3254 }
3255 
3256 /*@
3257   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3258   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3259 
3260   Collective
3261 
3262   Input Parameters:
3263 + fact - the factor matrix obtained with `MatGetFactor()`
3264 . mat  - the matrix
3265 . row  - the row permutation
3266 . col  - the column permutation
3267 - info - options for factorization, includes
3268 .vb
3269           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3270           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3271 .ve
3272 
3273   Level: developer
3274 
3275   Notes:
3276   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3277 
3278   Most users should employ the simplified `KSP` interface for linear solvers
3279   instead of working directly with matrix algebra routines such as this.
3280   See, e.g., `KSPCreate()`.
3281 
3282   Developer Note:
3283   The Fortran interface is not autogenerated as the
3284   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3285 
3286 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3287 @*/
3288 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3289 {
3290   MatFactorInfo tinfo;
3291 
3292   PetscFunctionBegin;
3293   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3294   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3295   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3296   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3297   if (info) PetscAssertPointer(info, 5);
3298   PetscValidType(fact, 1);
3299   PetscValidType(mat, 2);
3300   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3301   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3302   MatCheckPreallocated(mat, 2);
3303   if (!info) {
3304     PetscCall(MatFactorInfoInitialize(&tinfo));
3305     info = &tinfo;
3306   }
3307 
3308   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3309   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3310   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3311   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3312   PetscFunctionReturn(PETSC_SUCCESS);
3313 }
3314 
3315 /*@
3316   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3317   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3318 
3319   Collective
3320 
3321   Input Parameters:
3322 + fact - the factor matrix obtained with `MatGetFactor()`
3323 . mat  - the matrix
3324 - info - options for factorization
3325 
3326   Level: developer
3327 
3328   Notes:
3329   See `MatLUFactor()` for in-place factorization.  See
3330   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3331 
3332   Most users should employ the `KSP` interface for linear solvers
3333   instead of working directly with matrix algebra routines such as this.
3334   See, e.g., `KSPCreate()`.
3335 
3336   Developer Note:
3337   The Fortran interface is not autogenerated as the
3338   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3339 
3340 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3341 @*/
3342 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3343 {
3344   MatFactorInfo tinfo;
3345 
3346   PetscFunctionBegin;
3347   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3349   PetscValidType(fact, 1);
3350   PetscValidType(mat, 2);
3351   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3352   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,
3353              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3354 
3355   MatCheckPreallocated(mat, 2);
3356   if (!info) {
3357     PetscCall(MatFactorInfoInitialize(&tinfo));
3358     info = &tinfo;
3359   }
3360 
3361   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3362   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3363   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3364   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3365   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3366   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3367   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3368   PetscFunctionReturn(PETSC_SUCCESS);
3369 }
3370 
3371 /*@
3372   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3373   symmetric matrix.
3374 
3375   Collective
3376 
3377   Input Parameters:
3378 + mat  - the matrix
3379 . perm - row and column permutations
3380 - info - expected fill as ratio of original fill
3381 
3382   Level: developer
3383 
3384   Notes:
3385   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3386   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3387 
3388   Most users should employ the `KSP` interface for linear solvers
3389   instead of working directly with matrix algebra routines such as this.
3390   See, e.g., `KSPCreate()`.
3391 
3392   Developer Note:
3393   The Fortran interface is not autogenerated as the
3394   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3395 
3396 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3397           `MatGetOrdering()`
3398 @*/
3399 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3400 {
3401   MatFactorInfo tinfo;
3402 
3403   PetscFunctionBegin;
3404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3405   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3406   if (info) PetscAssertPointer(info, 3);
3407   PetscValidType(mat, 1);
3408   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3409   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3410   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3411   MatCheckPreallocated(mat, 1);
3412   if (!info) {
3413     PetscCall(MatFactorInfoInitialize(&tinfo));
3414     info = &tinfo;
3415   }
3416 
3417   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3418   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3419   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3420   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3421   PetscFunctionReturn(PETSC_SUCCESS);
3422 }
3423 
3424 /*@
3425   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3426   of a symmetric matrix.
3427 
3428   Collective
3429 
3430   Input Parameters:
3431 + fact - the factor matrix obtained with `MatGetFactor()`
3432 . mat  - the matrix
3433 . perm - row and column permutations
3434 - info - options for factorization, includes
3435 .vb
3436           fill - expected fill as ratio of original fill.
3437           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3438                    Run with the option -info to determine an optimal value to use
3439 .ve
3440 
3441   Level: developer
3442 
3443   Notes:
3444   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3445   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3446 
3447   Most users should employ the `KSP` interface for linear solvers
3448   instead of working directly with matrix algebra routines such as this.
3449   See, e.g., `KSPCreate()`.
3450 
3451   Developer Note:
3452   The Fortran interface is not autogenerated as the
3453   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3454 
3455 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3456           `MatGetOrdering()`
3457 @*/
3458 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3459 {
3460   MatFactorInfo tinfo;
3461 
3462   PetscFunctionBegin;
3463   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3465   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3466   if (info) PetscAssertPointer(info, 4);
3467   PetscValidType(fact, 1);
3468   PetscValidType(mat, 2);
3469   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3470   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3471   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3472   MatCheckPreallocated(mat, 2);
3473   if (!info) {
3474     PetscCall(MatFactorInfoInitialize(&tinfo));
3475     info = &tinfo;
3476   }
3477 
3478   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3479   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3480   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3481   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3482   PetscFunctionReturn(PETSC_SUCCESS);
3483 }
3484 
3485 /*@
3486   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3487   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3488   `MatCholeskyFactorSymbolic()`.
3489 
3490   Collective
3491 
3492   Input Parameters:
3493 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3494 . mat  - the initial matrix that is to be factored
3495 - info - options for factorization
3496 
3497   Level: developer
3498 
3499   Note:
3500   Most users should employ the `KSP` interface for linear solvers
3501   instead of working directly with matrix algebra routines such as this.
3502   See, e.g., `KSPCreate()`.
3503 
3504   Developer Note:
3505   The Fortran interface is not autogenerated as the
3506   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3507 
3508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3509 @*/
3510 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3511 {
3512   MatFactorInfo tinfo;
3513 
3514   PetscFunctionBegin;
3515   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3517   PetscValidType(fact, 1);
3518   PetscValidType(mat, 2);
3519   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3520   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,
3521              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3522   MatCheckPreallocated(mat, 2);
3523   if (!info) {
3524     PetscCall(MatFactorInfoInitialize(&tinfo));
3525     info = &tinfo;
3526   }
3527 
3528   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3529   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3530   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3531   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3532   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3533   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3534   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3535   PetscFunctionReturn(PETSC_SUCCESS);
3536 }
3537 
3538 /*@
3539   MatQRFactor - Performs in-place QR factorization of matrix.
3540 
3541   Collective
3542 
3543   Input Parameters:
3544 + mat  - the matrix
3545 . col  - column permutation
3546 - info - options for factorization, includes
3547 .vb
3548           fill - expected fill as ratio of original fill.
3549           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3550                    Run with the option -info to determine an optimal value to use
3551 .ve
3552 
3553   Level: developer
3554 
3555   Notes:
3556   Most users should employ the `KSP` interface for linear solvers
3557   instead of working directly with matrix algebra routines such as this.
3558   See, e.g., `KSPCreate()`.
3559 
3560   This changes the state of the matrix to a factored matrix; it cannot be used
3561   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3562 
3563   Developer Note:
3564   The Fortran interface is not autogenerated as the
3565   interface definition cannot be generated correctly [due to MatFactorInfo]
3566 
3567 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3568           `MatSetUnfactored()`
3569 @*/
3570 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3571 {
3572   PetscFunctionBegin;
3573   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3574   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3575   if (info) PetscAssertPointer(info, 3);
3576   PetscValidType(mat, 1);
3577   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3578   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3579   MatCheckPreallocated(mat, 1);
3580   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3581   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3582   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3583   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3584   PetscFunctionReturn(PETSC_SUCCESS);
3585 }
3586 
3587 /*@
3588   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3589   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3590 
3591   Collective
3592 
3593   Input Parameters:
3594 + fact - the factor matrix obtained with `MatGetFactor()`
3595 . mat  - the matrix
3596 . col  - column permutation
3597 - info - options for factorization, includes
3598 .vb
3599           fill - expected fill as ratio of original fill.
3600           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3601                    Run with the option -info to determine an optimal value to use
3602 .ve
3603 
3604   Level: developer
3605 
3606   Note:
3607   Most users should employ the `KSP` interface for linear solvers
3608   instead of working directly with matrix algebra routines such as this.
3609   See, e.g., `KSPCreate()`.
3610 
3611   Developer Note:
3612   The Fortran interface is not autogenerated as the
3613   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3614 
3615 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3616 @*/
3617 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3618 {
3619   MatFactorInfo tinfo;
3620 
3621   PetscFunctionBegin;
3622   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3623   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3624   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3625   if (info) PetscAssertPointer(info, 4);
3626   PetscValidType(fact, 1);
3627   PetscValidType(mat, 2);
3628   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3629   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3630   MatCheckPreallocated(mat, 2);
3631   if (!info) {
3632     PetscCall(MatFactorInfoInitialize(&tinfo));
3633     info = &tinfo;
3634   }
3635 
3636   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3637   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3638   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3639   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3640   PetscFunctionReturn(PETSC_SUCCESS);
3641 }
3642 
3643 /*@
3644   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3645   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3646 
3647   Collective
3648 
3649   Input Parameters:
3650 + fact - the factor matrix obtained with `MatGetFactor()`
3651 . mat  - the matrix
3652 - info - options for factorization
3653 
3654   Level: developer
3655 
3656   Notes:
3657   See `MatQRFactor()` for in-place factorization.
3658 
3659   Most users should employ the `KSP` interface for linear solvers
3660   instead of working directly with matrix algebra routines such as this.
3661   See, e.g., `KSPCreate()`.
3662 
3663   Developer Note:
3664   The Fortran interface is not autogenerated as the
3665   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3666 
3667 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3668 @*/
3669 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3670 {
3671   MatFactorInfo tinfo;
3672 
3673   PetscFunctionBegin;
3674   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3675   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3676   PetscValidType(fact, 1);
3677   PetscValidType(mat, 2);
3678   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3679   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,
3680              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3681 
3682   MatCheckPreallocated(mat, 2);
3683   if (!info) {
3684     PetscCall(MatFactorInfoInitialize(&tinfo));
3685     info = &tinfo;
3686   }
3687 
3688   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3689   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3690   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3691   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3692   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3693   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3694   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3695   PetscFunctionReturn(PETSC_SUCCESS);
3696 }
3697 
3698 /*@
3699   MatSolve - Solves $A x = b$, given a factored matrix.
3700 
3701   Neighbor-wise Collective
3702 
3703   Input Parameters:
3704 + mat - the factored matrix
3705 - b   - the right-hand-side vector
3706 
3707   Output Parameter:
3708 . x - the result vector
3709 
3710   Level: developer
3711 
3712   Notes:
3713   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3714   call `MatSolve`(A,x,x).
3715 
3716   Most users should employ the `KSP` interface for linear solvers
3717   instead of working directly with matrix algebra routines such as this.
3718   See, e.g., `KSPCreate()`.
3719 
3720 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3721 @*/
3722 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3723 {
3724   PetscFunctionBegin;
3725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3726   PetscValidType(mat, 1);
3727   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3728   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3729   PetscCheckSameComm(mat, 1, b, 2);
3730   PetscCheckSameComm(mat, 1, x, 3);
3731   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3732   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);
3733   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);
3734   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);
3735   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3736   MatCheckPreallocated(mat, 1);
3737 
3738   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3739   PetscCall(VecFlag(x, mat->factorerrortype));
3740   if (mat->factorerrortype) {
3741     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3742   } else PetscUseTypeMethod(mat, solve, b, x);
3743   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3744   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3745   PetscFunctionReturn(PETSC_SUCCESS);
3746 }
3747 
3748 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3749 {
3750   Vec      b, x;
3751   PetscInt N, i;
3752   PetscErrorCode (*f)(Mat, Vec, Vec);
3753   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3754 
3755   PetscFunctionBegin;
3756   if (A->factorerrortype) {
3757     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3758     PetscCall(MatSetInf(X));
3759     PetscFunctionReturn(PETSC_SUCCESS);
3760   }
3761   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3762   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3763   PetscCall(MatBoundToCPU(A, &Abound));
3764   if (!Abound) {
3765     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3766     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3767   }
3768 #if PetscDefined(HAVE_CUDA)
3769   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3770   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3771 #elif PetscDefined(HAVE_HIP)
3772   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3773   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3774 #endif
3775   PetscCall(MatGetSize(B, NULL, &N));
3776   for (i = 0; i < N; i++) {
3777     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3778     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3779     PetscCall((*f)(A, b, x));
3780     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3781     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3782   }
3783   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3784   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3785   PetscFunctionReturn(PETSC_SUCCESS);
3786 }
3787 
3788 /*@
3789   MatMatSolve - Solves $A X = B$, given a factored matrix.
3790 
3791   Neighbor-wise Collective
3792 
3793   Input Parameters:
3794 + A - the factored matrix
3795 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3796 
3797   Output Parameter:
3798 . X - the result matrix (dense matrix)
3799 
3800   Level: developer
3801 
3802   Note:
3803   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3804   otherwise, `B` and `X` cannot be the same.
3805 
3806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3807 @*/
3808 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3809 {
3810   PetscFunctionBegin;
3811   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3812   PetscValidType(A, 1);
3813   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3814   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3815   PetscCheckSameComm(A, 1, B, 2);
3816   PetscCheckSameComm(A, 1, X, 3);
3817   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);
3818   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);
3819   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");
3820   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3821   MatCheckPreallocated(A, 1);
3822 
3823   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3824   if (!A->ops->matsolve) {
3825     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3826     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3827   } else PetscUseTypeMethod(A, matsolve, B, X);
3828   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3829   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3830   PetscFunctionReturn(PETSC_SUCCESS);
3831 }
3832 
3833 /*@
3834   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3835 
3836   Neighbor-wise Collective
3837 
3838   Input Parameters:
3839 + A - the factored matrix
3840 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3841 
3842   Output Parameter:
3843 . X - the result matrix (dense matrix)
3844 
3845   Level: developer
3846 
3847   Note:
3848   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3849   call `MatMatSolveTranspose`(A,X,X).
3850 
3851 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3852 @*/
3853 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3854 {
3855   PetscFunctionBegin;
3856   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3857   PetscValidType(A, 1);
3858   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3859   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3860   PetscCheckSameComm(A, 1, B, 2);
3861   PetscCheckSameComm(A, 1, X, 3);
3862   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3863   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);
3864   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);
3865   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);
3866   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");
3867   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3868   MatCheckPreallocated(A, 1);
3869 
3870   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3871   if (!A->ops->matsolvetranspose) {
3872     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3873     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3874   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3875   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3876   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3877   PetscFunctionReturn(PETSC_SUCCESS);
3878 }
3879 
3880 /*@
3881   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3882 
3883   Neighbor-wise Collective
3884 
3885   Input Parameters:
3886 + A  - the factored matrix
3887 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3888 
3889   Output Parameter:
3890 . X - the result matrix (dense matrix)
3891 
3892   Level: developer
3893 
3894   Note:
3895   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
3896   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3897 
3898 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3899 @*/
3900 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3901 {
3902   PetscFunctionBegin;
3903   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3904   PetscValidType(A, 1);
3905   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3906   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3907   PetscCheckSameComm(A, 1, Bt, 2);
3908   PetscCheckSameComm(A, 1, X, 3);
3909 
3910   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3911   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);
3912   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);
3913   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");
3914   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3915   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3916   MatCheckPreallocated(A, 1);
3917 
3918   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3919   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3920   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3921   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3922   PetscFunctionReturn(PETSC_SUCCESS);
3923 }
3924 
3925 /*@
3926   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3927   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3928 
3929   Neighbor-wise Collective
3930 
3931   Input Parameters:
3932 + mat - the factored matrix
3933 - b   - the right-hand-side vector
3934 
3935   Output Parameter:
3936 . x - the result vector
3937 
3938   Level: developer
3939 
3940   Notes:
3941   `MatSolve()` should be used for most applications, as it performs
3942   a forward solve followed by a backward solve.
3943 
3944   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3945   call `MatForwardSolve`(A,x,x).
3946 
3947   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3948   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3949   `MatForwardSolve()` solves $U^T*D y = b$, and
3950   `MatBackwardSolve()` solves $U x = y$.
3951   Thus they do not provide a symmetric preconditioner.
3952 
3953 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3954 @*/
3955 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3956 {
3957   PetscFunctionBegin;
3958   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3959   PetscValidType(mat, 1);
3960   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3961   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3962   PetscCheckSameComm(mat, 1, b, 2);
3963   PetscCheckSameComm(mat, 1, x, 3);
3964   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3965   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);
3966   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);
3967   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);
3968   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3969   MatCheckPreallocated(mat, 1);
3970 
3971   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3972   PetscUseTypeMethod(mat, forwardsolve, b, x);
3973   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3974   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3975   PetscFunctionReturn(PETSC_SUCCESS);
3976 }
3977 
3978 /*@
3979   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3980   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3981 
3982   Neighbor-wise Collective
3983 
3984   Input Parameters:
3985 + mat - the factored matrix
3986 - b   - the right-hand-side vector
3987 
3988   Output Parameter:
3989 . x - the result vector
3990 
3991   Level: developer
3992 
3993   Notes:
3994   `MatSolve()` should be used for most applications, as it performs
3995   a forward solve followed by a backward solve.
3996 
3997   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3998   call `MatBackwardSolve`(A,x,x).
3999 
4000   For matrix in `MATSEQBAIJ` format with block size larger than 1,
4001   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
4002   `MatForwardSolve()` solves $U^T*D y = b$, and
4003   `MatBackwardSolve()` solves $U x = y$.
4004   Thus they do not provide a symmetric preconditioner.
4005 
4006 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
4007 @*/
4008 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
4009 {
4010   PetscFunctionBegin;
4011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4012   PetscValidType(mat, 1);
4013   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4014   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4015   PetscCheckSameComm(mat, 1, b, 2);
4016   PetscCheckSameComm(mat, 1, x, 3);
4017   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4018   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);
4019   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);
4020   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);
4021   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4022   MatCheckPreallocated(mat, 1);
4023 
4024   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
4025   PetscUseTypeMethod(mat, backwardsolve, b, x);
4026   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
4027   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4028   PetscFunctionReturn(PETSC_SUCCESS);
4029 }
4030 
4031 /*@
4032   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
4033 
4034   Neighbor-wise Collective
4035 
4036   Input Parameters:
4037 + mat - the factored matrix
4038 . b   - the right-hand-side vector
4039 - y   - the vector to be added to
4040 
4041   Output Parameter:
4042 . x - the result vector
4043 
4044   Level: developer
4045 
4046   Note:
4047   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4048   call `MatSolveAdd`(A,x,y,x).
4049 
4050 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
4051 @*/
4052 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
4053 {
4054   PetscScalar one = 1.0;
4055   Vec         tmp;
4056 
4057   PetscFunctionBegin;
4058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4059   PetscValidType(mat, 1);
4060   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4061   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4062   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4063   PetscCheckSameComm(mat, 1, b, 2);
4064   PetscCheckSameComm(mat, 1, y, 3);
4065   PetscCheckSameComm(mat, 1, x, 4);
4066   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4067   PetscCheck(mat->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);
4068   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);
4069   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);
4070   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);
4071   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);
4072   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4073   MatCheckPreallocated(mat, 1);
4074 
4075   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4076   PetscCall(VecFlag(x, mat->factorerrortype));
4077   if (mat->factorerrortype) {
4078     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4079   } else if (mat->ops->solveadd) {
4080     PetscUseTypeMethod(mat, solveadd, b, y, x);
4081   } else {
4082     /* do the solve then the add manually */
4083     if (x != y) {
4084       PetscCall(MatSolve(mat, b, x));
4085       PetscCall(VecAXPY(x, one, y));
4086     } else {
4087       PetscCall(VecDuplicate(x, &tmp));
4088       PetscCall(VecCopy(x, tmp));
4089       PetscCall(MatSolve(mat, b, x));
4090       PetscCall(VecAXPY(x, one, tmp));
4091       PetscCall(VecDestroy(&tmp));
4092     }
4093   }
4094   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4095   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4096   PetscFunctionReturn(PETSC_SUCCESS);
4097 }
4098 
4099 /*@
4100   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4101 
4102   Neighbor-wise Collective
4103 
4104   Input Parameters:
4105 + mat - the factored matrix
4106 - b   - the right-hand-side vector
4107 
4108   Output Parameter:
4109 . x - the result vector
4110 
4111   Level: developer
4112 
4113   Notes:
4114   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4115   call `MatSolveTranspose`(A,x,x).
4116 
4117   Most users should employ the `KSP` interface for linear solvers
4118   instead of working directly with matrix algebra routines such as this.
4119   See, e.g., `KSPCreate()`.
4120 
4121 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4122 @*/
4123 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4124 {
4125   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4126 
4127   PetscFunctionBegin;
4128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4129   PetscValidType(mat, 1);
4130   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4131   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4132   PetscCheckSameComm(mat, 1, b, 2);
4133   PetscCheckSameComm(mat, 1, x, 3);
4134   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4135   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);
4136   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);
4137   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4138   MatCheckPreallocated(mat, 1);
4139   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4140   PetscCall(VecFlag(x, mat->factorerrortype));
4141   if (mat->factorerrortype) {
4142     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4143   } else {
4144     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4145     PetscCall((*f)(mat, b, x));
4146   }
4147   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4148   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4149   PetscFunctionReturn(PETSC_SUCCESS);
4150 }
4151 
4152 /*@
4153   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4154   factored matrix.
4155 
4156   Neighbor-wise Collective
4157 
4158   Input Parameters:
4159 + mat - the factored matrix
4160 . b   - the right-hand-side vector
4161 - y   - the vector to be added to
4162 
4163   Output Parameter:
4164 . x - the result vector
4165 
4166   Level: developer
4167 
4168   Note:
4169   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4170   call `MatSolveTransposeAdd`(A,x,y,x).
4171 
4172 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4173 @*/
4174 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4175 {
4176   PetscScalar one = 1.0;
4177   Vec         tmp;
4178   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4179 
4180   PetscFunctionBegin;
4181   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4182   PetscValidType(mat, 1);
4183   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4184   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4185   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4186   PetscCheckSameComm(mat, 1, b, 2);
4187   PetscCheckSameComm(mat, 1, y, 3);
4188   PetscCheckSameComm(mat, 1, x, 4);
4189   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4190   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);
4191   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);
4192   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);
4193   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);
4194   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4195   MatCheckPreallocated(mat, 1);
4196 
4197   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4198   PetscCall(VecFlag(x, mat->factorerrortype));
4199   if (mat->factorerrortype) {
4200     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4201   } else if (f) {
4202     PetscCall((*f)(mat, b, y, x));
4203   } else {
4204     /* do the solve then the add manually */
4205     if (x != y) {
4206       PetscCall(MatSolveTranspose(mat, b, x));
4207       PetscCall(VecAXPY(x, one, y));
4208     } else {
4209       PetscCall(VecDuplicate(x, &tmp));
4210       PetscCall(VecCopy(x, tmp));
4211       PetscCall(MatSolveTranspose(mat, b, x));
4212       PetscCall(VecAXPY(x, one, tmp));
4213       PetscCall(VecDestroy(&tmp));
4214     }
4215   }
4216   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4217   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4218   PetscFunctionReturn(PETSC_SUCCESS);
4219 }
4220 
4221 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4222 /*@
4223   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4224 
4225   Neighbor-wise Collective
4226 
4227   Input Parameters:
4228 + mat   - the matrix
4229 . b     - the right-hand side
4230 . omega - the relaxation factor
4231 . flag  - flag indicating the type of SOR (see below)
4232 . shift - diagonal shift
4233 . its   - the number of iterations
4234 - lits  - the number of local iterations
4235 
4236   Output Parameter:
4237 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4238 
4239   SOR Flags:
4240 +     `SOR_FORWARD_SWEEP` - forward SOR
4241 .     `SOR_BACKWARD_SWEEP` - backward SOR
4242 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4243 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4244 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4245 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4246 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4247 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4248   upper/lower triangular part of matrix to
4249   vector (with omega)
4250 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4251 
4252   Level: developer
4253 
4254   Notes:
4255   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4256   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4257   on each processor.
4258 
4259   Application programmers will not generally use `MatSOR()` directly,
4260   but instead will employ the `KSP`/`PC` interface.
4261 
4262   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4263 
4264   Most users should employ the `KSP` interface for linear solvers
4265   instead of working directly with matrix algebra routines such as this.
4266   See, e.g., `KSPCreate()`.
4267 
4268   Vectors `x` and `b` CANNOT be the same
4269 
4270   The flags are implemented as bitwise inclusive or operations.
4271   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4272   to specify a zero initial guess for SSOR.
4273 
4274   Developer Note:
4275   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4276 
4277 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4278 @*/
4279 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4280 {
4281   PetscFunctionBegin;
4282   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4283   PetscValidType(mat, 1);
4284   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4285   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4286   PetscCheckSameComm(mat, 1, b, 2);
4287   PetscCheckSameComm(mat, 1, x, 8);
4288   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4289   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4290   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);
4291   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);
4292   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);
4293   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4294   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4295   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4296 
4297   MatCheckPreallocated(mat, 1);
4298   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4299   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4300   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4301   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4302   PetscFunctionReturn(PETSC_SUCCESS);
4303 }
4304 
4305 /*
4306       Default matrix copy routine.
4307 */
4308 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4309 {
4310   PetscInt           i, rstart = 0, rend = 0, nz;
4311   const PetscInt    *cwork;
4312   const PetscScalar *vwork;
4313 
4314   PetscFunctionBegin;
4315   if (B->assembled) PetscCall(MatZeroEntries(B));
4316   if (str == SAME_NONZERO_PATTERN) {
4317     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4318     for (i = rstart; i < rend; i++) {
4319       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4320       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4321       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4322     }
4323   } else {
4324     PetscCall(MatAYPX(B, 0.0, A, str));
4325   }
4326   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4327   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4328   PetscFunctionReturn(PETSC_SUCCESS);
4329 }
4330 
4331 /*@
4332   MatCopy - Copies a matrix to another matrix.
4333 
4334   Collective
4335 
4336   Input Parameters:
4337 + A   - the matrix
4338 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4339 
4340   Output Parameter:
4341 . B - where the copy is put
4342 
4343   Level: intermediate
4344 
4345   Notes:
4346   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4347 
4348   `MatCopy()` copies the matrix entries of a matrix to another existing
4349   matrix (after first zeroing the second matrix).  A related routine is
4350   `MatConvert()`, which first creates a new matrix and then copies the data.
4351 
4352 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4353 @*/
4354 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4355 {
4356   PetscInt i;
4357 
4358   PetscFunctionBegin;
4359   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4360   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4361   PetscValidType(A, 1);
4362   PetscValidType(B, 2);
4363   PetscCheckSameComm(A, 1, B, 2);
4364   MatCheckPreallocated(B, 2);
4365   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4366   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4367   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,
4368              A->cmap->N, B->cmap->N);
4369   MatCheckPreallocated(A, 1);
4370   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4371 
4372   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4373   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4374   else PetscCall(MatCopy_Basic(A, B, str));
4375 
4376   B->stencil.dim = A->stencil.dim;
4377   B->stencil.noc = A->stencil.noc;
4378   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4379     B->stencil.dims[i]   = A->stencil.dims[i];
4380     B->stencil.starts[i] = A->stencil.starts[i];
4381   }
4382 
4383   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4384   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4385   PetscFunctionReturn(PETSC_SUCCESS);
4386 }
4387 
4388 /*@
4389   MatConvert - Converts a matrix to another matrix, either of the same
4390   or different type.
4391 
4392   Collective
4393 
4394   Input Parameters:
4395 + mat     - the matrix
4396 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4397             same type as the original matrix.
4398 - reuse   - denotes if the destination matrix is to be created or reused.
4399             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
4400             `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).
4401 
4402   Output Parameter:
4403 . M - pointer to place new matrix
4404 
4405   Level: intermediate
4406 
4407   Notes:
4408   `MatConvert()` first creates a new matrix and then copies the data from
4409   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4410   entries of one matrix to another already existing matrix context.
4411 
4412   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4413   the MPI communicator of the generated matrix is always the same as the communicator
4414   of the input matrix.
4415 
4416 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4417 @*/
4418 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4419 {
4420   PetscBool  sametype, issame, flg;
4421   PetscBool3 issymmetric, ishermitian;
4422   char       convname[256], mtype[256];
4423   Mat        B;
4424 
4425   PetscFunctionBegin;
4426   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4427   PetscValidType(mat, 1);
4428   PetscAssertPointer(M, 4);
4429   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4430   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4431   MatCheckPreallocated(mat, 1);
4432 
4433   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4434   if (flg) newtype = mtype;
4435 
4436   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4437   PetscCall(PetscStrcmp(newtype, "same", &issame));
4438   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4439   if (reuse == MAT_REUSE_MATRIX) {
4440     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4441     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4442   }
4443 
4444   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4445     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4446     PetscFunctionReturn(PETSC_SUCCESS);
4447   }
4448 
4449   /* Cache Mat options because some converters use MatHeaderReplace  */
4450   issymmetric = mat->symmetric;
4451   ishermitian = mat->hermitian;
4452 
4453   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4454     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4455     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4456   } else {
4457     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4458     const char *prefix[3]                                 = {"seq", "mpi", ""};
4459     PetscInt    i;
4460     /*
4461        Order of precedence:
4462        0) See if newtype is a superclass of the current matrix.
4463        1) See if a specialized converter is known to the current matrix.
4464        2) See if a specialized converter is known to the desired matrix class.
4465        3) See if a good general converter is registered for the desired class
4466           (as of 6/27/03 only MATMPIADJ falls into this category).
4467        4) See if a good general converter is known for the current matrix.
4468        5) Use a really basic converter.
4469     */
4470 
4471     /* 0) See if newtype is a superclass of the current matrix.
4472           i.e mat is mpiaij and newtype is aij */
4473     for (i = 0; i < 2; i++) {
4474       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4475       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4476       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4477       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4478       if (flg) {
4479         if (reuse == MAT_INPLACE_MATRIX) {
4480           PetscCall(PetscInfo(mat, "Early return\n"));
4481           PetscFunctionReturn(PETSC_SUCCESS);
4482         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4483           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4484           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4485           PetscFunctionReturn(PETSC_SUCCESS);
4486         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4487           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4488           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4489           PetscFunctionReturn(PETSC_SUCCESS);
4490         }
4491       }
4492     }
4493     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4494     for (i = 0; i < 3; i++) {
4495       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4496       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4497       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4498       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4499       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4500       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4501       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4502       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4503       if (conv) goto foundconv;
4504     }
4505 
4506     /* 2)  See if a specialized converter is known to the desired matrix class. */
4507     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4508     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4509     PetscCall(MatSetType(B, newtype));
4510     for (i = 0; i < 3; i++) {
4511       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4512       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4513       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4514       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4515       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4516       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4517       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4518       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4519       if (conv) {
4520         PetscCall(MatDestroy(&B));
4521         goto foundconv;
4522       }
4523     }
4524 
4525     /* 3) See if a good general converter is registered for the desired class */
4526     conv = B->ops->convertfrom;
4527     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4528     PetscCall(MatDestroy(&B));
4529     if (conv) goto foundconv;
4530 
4531     /* 4) See if a good general converter is known for the current matrix */
4532     if (mat->ops->convert) conv = mat->ops->convert;
4533     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4534     if (conv) goto foundconv;
4535 
4536     /* 5) Use a really basic converter. */
4537     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4538     conv = MatConvert_Basic;
4539 
4540   foundconv:
4541     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4542     PetscCall((*conv)(mat, newtype, reuse, M));
4543     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4544       /* the block sizes must be same if the mappings are copied over */
4545       (*M)->rmap->bs = mat->rmap->bs;
4546       (*M)->cmap->bs = mat->cmap->bs;
4547       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4548       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4549       (*M)->rmap->mapping = mat->rmap->mapping;
4550       (*M)->cmap->mapping = mat->cmap->mapping;
4551     }
4552     (*M)->stencil.dim = mat->stencil.dim;
4553     (*M)->stencil.noc = mat->stencil.noc;
4554     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4555       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4556       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4557     }
4558     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4559   }
4560   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4561 
4562   /* Copy Mat options */
4563   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4564   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4565   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4566   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4567   PetscFunctionReturn(PETSC_SUCCESS);
4568 }
4569 
4570 /*@
4571   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4572 
4573   Not Collective
4574 
4575   Input Parameter:
4576 . mat - the matrix, must be a factored matrix
4577 
4578   Output Parameter:
4579 . type - the string name of the package (do not free this string)
4580 
4581   Level: intermediate
4582 
4583   Fortran Note:
4584   Pass in an empty string that is long enough and the package name will be copied into it.
4585 
4586 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4587 @*/
4588 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4589 {
4590   PetscErrorCode (*conv)(Mat, MatSolverType *);
4591 
4592   PetscFunctionBegin;
4593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4594   PetscValidType(mat, 1);
4595   PetscAssertPointer(type, 2);
4596   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4597   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4598   if (conv) PetscCall((*conv)(mat, type));
4599   else *type = MATSOLVERPETSC;
4600   PetscFunctionReturn(PETSC_SUCCESS);
4601 }
4602 
4603 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4604 struct _MatSolverTypeForSpecifcType {
4605   MatType mtype;
4606   /* no entry for MAT_FACTOR_NONE */
4607   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4608   MatSolverTypeForSpecifcType next;
4609 };
4610 
4611 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4612 struct _MatSolverTypeHolder {
4613   char                       *name;
4614   MatSolverTypeForSpecifcType handlers;
4615   MatSolverTypeHolder         next;
4616 };
4617 
4618 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4619 
4620 /*@C
4621   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4622 
4623   Logically Collective, No Fortran Support
4624 
4625   Input Parameters:
4626 + package      - name of the package, for example petsc or superlu
4627 . mtype        - the matrix type that works with this package
4628 . ftype        - the type of factorization supported by the package
4629 - createfactor - routine that will create the factored matrix ready to be used
4630 
4631   Level: developer
4632 
4633 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4634   `MatGetFactor()`
4635 @*/
4636 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4637 {
4638   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4639   PetscBool                   flg;
4640   MatSolverTypeForSpecifcType inext, iprev = NULL;
4641 
4642   PetscFunctionBegin;
4643   PetscCall(MatInitializePackage());
4644   if (!next) {
4645     PetscCall(PetscNew(&MatSolverTypeHolders));
4646     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4647     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4648     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4649     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4650     PetscFunctionReturn(PETSC_SUCCESS);
4651   }
4652   while (next) {
4653     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4654     if (flg) {
4655       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4656       inext = next->handlers;
4657       while (inext) {
4658         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4659         if (flg) {
4660           inext->createfactor[(int)ftype - 1] = createfactor;
4661           PetscFunctionReturn(PETSC_SUCCESS);
4662         }
4663         iprev = inext;
4664         inext = inext->next;
4665       }
4666       PetscCall(PetscNew(&iprev->next));
4667       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4668       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4669       PetscFunctionReturn(PETSC_SUCCESS);
4670     }
4671     prev = next;
4672     next = next->next;
4673   }
4674   PetscCall(PetscNew(&prev->next));
4675   PetscCall(PetscStrallocpy(package, &prev->next->name));
4676   PetscCall(PetscNew(&prev->next->handlers));
4677   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4678   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4679   PetscFunctionReturn(PETSC_SUCCESS);
4680 }
4681 
4682 /*@C
4683   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4684 
4685   Input Parameters:
4686 + 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
4687 . ftype - the type of factorization supported by the type
4688 - mtype - the matrix type that works with this type
4689 
4690   Output Parameters:
4691 + foundtype    - `PETSC_TRUE` if the type was registered
4692 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4693 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4694 
4695   Calling sequence of `createfactor`:
4696 + A     - the matrix providing the factor matrix
4697 . ftype - the `MatFactorType` of the factor requested
4698 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4699 
4700   Level: developer
4701 
4702   Note:
4703   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4704   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4705   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4706 
4707 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4708           `MatInitializePackage()`
4709 @*/
4710 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4711 {
4712   MatSolverTypeHolder         next = MatSolverTypeHolders;
4713   PetscBool                   flg;
4714   MatSolverTypeForSpecifcType inext;
4715 
4716   PetscFunctionBegin;
4717   if (foundtype) *foundtype = PETSC_FALSE;
4718   if (foundmtype) *foundmtype = PETSC_FALSE;
4719   if (createfactor) *createfactor = NULL;
4720 
4721   if (type) {
4722     while (next) {
4723       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4724       if (flg) {
4725         if (foundtype) *foundtype = PETSC_TRUE;
4726         inext = next->handlers;
4727         while (inext) {
4728           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4729           if (flg) {
4730             if (foundmtype) *foundmtype = PETSC_TRUE;
4731             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4732             PetscFunctionReturn(PETSC_SUCCESS);
4733           }
4734           inext = inext->next;
4735         }
4736       }
4737       next = next->next;
4738     }
4739   } else {
4740     while (next) {
4741       inext = next->handlers;
4742       while (inext) {
4743         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4744         if (flg && inext->createfactor[(int)ftype - 1]) {
4745           if (foundtype) *foundtype = PETSC_TRUE;
4746           if (foundmtype) *foundmtype = PETSC_TRUE;
4747           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4748           PetscFunctionReturn(PETSC_SUCCESS);
4749         }
4750         inext = inext->next;
4751       }
4752       next = next->next;
4753     }
4754     /* try with base classes inext->mtype */
4755     next = MatSolverTypeHolders;
4756     while (next) {
4757       inext = next->handlers;
4758       while (inext) {
4759         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4760         if (flg && inext->createfactor[(int)ftype - 1]) {
4761           if (foundtype) *foundtype = PETSC_TRUE;
4762           if (foundmtype) *foundmtype = PETSC_TRUE;
4763           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4764           PetscFunctionReturn(PETSC_SUCCESS);
4765         }
4766         inext = inext->next;
4767       }
4768       next = next->next;
4769     }
4770   }
4771   PetscFunctionReturn(PETSC_SUCCESS);
4772 }
4773 
4774 PetscErrorCode MatSolverTypeDestroy(void)
4775 {
4776   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4777   MatSolverTypeForSpecifcType inext, iprev;
4778 
4779   PetscFunctionBegin;
4780   while (next) {
4781     PetscCall(PetscFree(next->name));
4782     inext = next->handlers;
4783     while (inext) {
4784       PetscCall(PetscFree(inext->mtype));
4785       iprev = inext;
4786       inext = inext->next;
4787       PetscCall(PetscFree(iprev));
4788     }
4789     prev = next;
4790     next = next->next;
4791     PetscCall(PetscFree(prev));
4792   }
4793   MatSolverTypeHolders = NULL;
4794   PetscFunctionReturn(PETSC_SUCCESS);
4795 }
4796 
4797 /*@
4798   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4799 
4800   Logically Collective
4801 
4802   Input Parameter:
4803 . mat - the matrix
4804 
4805   Output Parameter:
4806 . flg - `PETSC_TRUE` if uses the ordering
4807 
4808   Level: developer
4809 
4810   Note:
4811   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4812   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4813 
4814 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4815 @*/
4816 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4817 {
4818   PetscFunctionBegin;
4819   *flg = mat->canuseordering;
4820   PetscFunctionReturn(PETSC_SUCCESS);
4821 }
4822 
4823 /*@
4824   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4825 
4826   Logically Collective
4827 
4828   Input Parameters:
4829 + mat   - the matrix obtained with `MatGetFactor()`
4830 - ftype - the factorization type to be used
4831 
4832   Output Parameter:
4833 . otype - the preferred ordering type
4834 
4835   Level: developer
4836 
4837 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4838 @*/
4839 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4840 {
4841   PetscFunctionBegin;
4842   *otype = mat->preferredordering[ftype];
4843   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4844   PetscFunctionReturn(PETSC_SUCCESS);
4845 }
4846 
4847 /*@
4848   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4849 
4850   Collective
4851 
4852   Input Parameters:
4853 + mat   - the matrix
4854 . 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
4855           the other criteria is returned
4856 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4857 
4858   Output Parameter:
4859 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4860 
4861   Options Database Keys:
4862 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4863 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4864                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4865 
4866   Level: intermediate
4867 
4868   Notes:
4869   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4870   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4871 
4872   Users usually access the factorization solvers via `KSP`
4873 
4874   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4875   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
4876 
4877   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4878   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4879   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4880 
4881   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4882   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4883   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4884 
4885   Developer Note:
4886   This should actually be called `MatCreateFactor()` since it creates a new factor object
4887 
4888 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4889           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4890           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4891 @*/
4892 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4893 {
4894   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4895   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4896 
4897   PetscFunctionBegin;
4898   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4899   PetscValidType(mat, 1);
4900 
4901   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4902   MatCheckPreallocated(mat, 1);
4903 
4904   PetscCall(MatIsShell(mat, &shell));
4905   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4906   if (hasop) {
4907     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4908     PetscFunctionReturn(PETSC_SUCCESS);
4909   }
4910 
4911   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4912   if (!foundtype) {
4913     if (type) {
4914       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],
4915               ((PetscObject)mat)->type_name, type);
4916     } else {
4917       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);
4918     }
4919   }
4920   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4921   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);
4922 
4923   PetscCall((*conv)(mat, ftype, f));
4924   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4925   PetscFunctionReturn(PETSC_SUCCESS);
4926 }
4927 
4928 /*@
4929   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4930 
4931   Not Collective
4932 
4933   Input Parameters:
4934 + mat   - the matrix
4935 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4936 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4937 
4938   Output Parameter:
4939 . flg - PETSC_TRUE if the factorization is available
4940 
4941   Level: intermediate
4942 
4943   Notes:
4944   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4945   such as pastix, superlu, mumps etc.
4946 
4947   PETSc must have been ./configure to use the external solver, using the option --download-package
4948 
4949   Developer Note:
4950   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4951 
4952 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4953           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4954 @*/
4955 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4956 {
4957   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4958 
4959   PetscFunctionBegin;
4960   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4961   PetscAssertPointer(flg, 4);
4962 
4963   *flg = PETSC_FALSE;
4964   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4965 
4966   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4967   MatCheckPreallocated(mat, 1);
4968 
4969   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4970   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4971   PetscFunctionReturn(PETSC_SUCCESS);
4972 }
4973 
4974 /*@
4975   MatDuplicate - Duplicates a matrix including the non-zero structure.
4976 
4977   Collective
4978 
4979   Input Parameters:
4980 + mat - the matrix
4981 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4982         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4983 
4984   Output Parameter:
4985 . M - pointer to place new matrix
4986 
4987   Level: intermediate
4988 
4989   Notes:
4990   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4991 
4992   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4993 
4994   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.
4995 
4996   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4997   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4998   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4999 
5000 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
5001 @*/
5002 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
5003 {
5004   Mat         B;
5005   VecType     vtype;
5006   PetscInt    i;
5007   PetscObject dm, container_h, container_d;
5008   void (*viewf)(void);
5009 
5010   PetscFunctionBegin;
5011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5012   PetscValidType(mat, 1);
5013   PetscAssertPointer(M, 3);
5014   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
5015   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5016   MatCheckPreallocated(mat, 1);
5017 
5018   *M = NULL;
5019   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
5020   PetscUseTypeMethod(mat, duplicate, op, M);
5021   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
5022   B = *M;
5023 
5024   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
5025   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
5026   PetscCall(MatGetVecType(mat, &vtype));
5027   PetscCall(MatSetVecType(B, vtype));
5028 
5029   B->stencil.dim = mat->stencil.dim;
5030   B->stencil.noc = mat->stencil.noc;
5031   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
5032     B->stencil.dims[i]   = mat->stencil.dims[i];
5033     B->stencil.starts[i] = mat->stencil.starts[i];
5034   }
5035 
5036   B->nooffproczerorows = mat->nooffproczerorows;
5037   B->nooffprocentries  = mat->nooffprocentries;
5038 
5039   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
5040   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
5041   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
5042   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
5043   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
5044   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
5045   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
5046   PetscCall(PetscObjectStateIncrease((PetscObject)B));
5047   PetscFunctionReturn(PETSC_SUCCESS);
5048 }
5049 
5050 /*@
5051   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
5052 
5053   Logically Collective
5054 
5055   Input Parameter:
5056 . mat - the matrix
5057 
5058   Output Parameter:
5059 . v - the diagonal of the matrix
5060 
5061   Level: intermediate
5062 
5063   Note:
5064   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5065   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5066   is larger than `ndiag`, the values of the remaining entries are unspecified.
5067 
5068   Currently only correct in parallel for square matrices.
5069 
5070 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5071 @*/
5072 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5073 {
5074   PetscFunctionBegin;
5075   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5076   PetscValidType(mat, 1);
5077   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5078   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5079   MatCheckPreallocated(mat, 1);
5080   if (PetscDefined(USE_DEBUG)) {
5081     PetscInt nv, row, col, ndiag;
5082 
5083     PetscCall(VecGetLocalSize(v, &nv));
5084     PetscCall(MatGetLocalSize(mat, &row, &col));
5085     ndiag = PetscMin(row, col);
5086     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);
5087   }
5088 
5089   PetscUseTypeMethod(mat, getdiagonal, v);
5090   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5091   PetscFunctionReturn(PETSC_SUCCESS);
5092 }
5093 
5094 /*@
5095   MatGetRowMin - Gets the minimum value (of the real part) of each
5096   row of the matrix
5097 
5098   Logically Collective
5099 
5100   Input Parameter:
5101 . mat - the matrix
5102 
5103   Output Parameters:
5104 + v   - the vector for storing the maximums
5105 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5106 
5107   Level: intermediate
5108 
5109   Note:
5110   The result of this call are the same as if one converted the matrix to dense format
5111   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5112 
5113   This code is only implemented for a couple of matrix formats.
5114 
5115 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5116           `MatGetRowMax()`
5117 @*/
5118 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5119 {
5120   PetscFunctionBegin;
5121   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5122   PetscValidType(mat, 1);
5123   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5124   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5125 
5126   if (!mat->cmap->N) {
5127     PetscCall(VecSet(v, PETSC_MAX_REAL));
5128     if (idx) {
5129       PetscInt i, m = mat->rmap->n;
5130       for (i = 0; i < m; i++) idx[i] = -1;
5131     }
5132   } else {
5133     MatCheckPreallocated(mat, 1);
5134   }
5135   PetscUseTypeMethod(mat, getrowmin, v, idx);
5136   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5137   PetscFunctionReturn(PETSC_SUCCESS);
5138 }
5139 
5140 /*@
5141   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5142   row of the matrix
5143 
5144   Logically Collective
5145 
5146   Input Parameter:
5147 . mat - the matrix
5148 
5149   Output Parameters:
5150 + v   - the vector for storing the minimums
5151 - idx - the indices of the column found for each row (or `NULL` if not needed)
5152 
5153   Level: intermediate
5154 
5155   Notes:
5156   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5157   row is 0 (the first column).
5158 
5159   This code is only implemented for a couple of matrix formats.
5160 
5161 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5162 @*/
5163 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5164 {
5165   PetscFunctionBegin;
5166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5167   PetscValidType(mat, 1);
5168   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5169   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5170   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5171 
5172   if (!mat->cmap->N) {
5173     PetscCall(VecSet(v, 0.0));
5174     if (idx) {
5175       PetscInt i, m = mat->rmap->n;
5176       for (i = 0; i < m; i++) idx[i] = -1;
5177     }
5178   } else {
5179     MatCheckPreallocated(mat, 1);
5180     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5181     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5182   }
5183   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5184   PetscFunctionReturn(PETSC_SUCCESS);
5185 }
5186 
5187 /*@
5188   MatGetRowMax - Gets the maximum value (of the real part) of each
5189   row of the matrix
5190 
5191   Logically Collective
5192 
5193   Input Parameter:
5194 . mat - the matrix
5195 
5196   Output Parameters:
5197 + v   - the vector for storing the maximums
5198 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5199 
5200   Level: intermediate
5201 
5202   Notes:
5203   The result of this call are the same as if one converted the matrix to dense format
5204   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5205 
5206   This code is only implemented for a couple of matrix formats.
5207 
5208 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5209 @*/
5210 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5211 {
5212   PetscFunctionBegin;
5213   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5214   PetscValidType(mat, 1);
5215   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5216   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5217 
5218   if (!mat->cmap->N) {
5219     PetscCall(VecSet(v, PETSC_MIN_REAL));
5220     if (idx) {
5221       PetscInt i, m = mat->rmap->n;
5222       for (i = 0; i < m; i++) idx[i] = -1;
5223     }
5224   } else {
5225     MatCheckPreallocated(mat, 1);
5226     PetscUseTypeMethod(mat, getrowmax, v, idx);
5227   }
5228   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5229   PetscFunctionReturn(PETSC_SUCCESS);
5230 }
5231 
5232 /*@
5233   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5234   row of the matrix
5235 
5236   Logically Collective
5237 
5238   Input Parameter:
5239 . mat - the matrix
5240 
5241   Output Parameters:
5242 + v   - the vector for storing the maximums
5243 - idx - the indices of the column found for each row (or `NULL` if not needed)
5244 
5245   Level: intermediate
5246 
5247   Notes:
5248   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5249   row is 0 (the first column).
5250 
5251   This code is only implemented for a couple of matrix formats.
5252 
5253 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5254 @*/
5255 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5256 {
5257   PetscFunctionBegin;
5258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5259   PetscValidType(mat, 1);
5260   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5262 
5263   if (!mat->cmap->N) {
5264     PetscCall(VecSet(v, 0.0));
5265     if (idx) {
5266       PetscInt i, m = mat->rmap->n;
5267       for (i = 0; i < m; i++) idx[i] = -1;
5268     }
5269   } else {
5270     MatCheckPreallocated(mat, 1);
5271     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5272     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5273   }
5274   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5275   PetscFunctionReturn(PETSC_SUCCESS);
5276 }
5277 
5278 /*@
5279   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5280 
5281   Logically Collective
5282 
5283   Input Parameter:
5284 . mat - the matrix
5285 
5286   Output Parameter:
5287 . v - the vector for storing the sum
5288 
5289   Level: intermediate
5290 
5291   This code is only implemented for a couple of matrix formats.
5292 
5293 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5294 @*/
5295 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
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 
5303   if (!mat->cmap->N) {
5304     PetscCall(VecSet(v, 0.0));
5305   } else {
5306     MatCheckPreallocated(mat, 1);
5307     PetscUseTypeMethod(mat, getrowsumabs, v);
5308   }
5309   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5310   PetscFunctionReturn(PETSC_SUCCESS);
5311 }
5312 
5313 /*@
5314   MatGetRowSum - Gets the sum of each row of the matrix
5315 
5316   Logically or Neighborhood Collective
5317 
5318   Input Parameter:
5319 . mat - the matrix
5320 
5321   Output Parameter:
5322 . v - the vector for storing the sum of rows
5323 
5324   Level: intermediate
5325 
5326   Note:
5327   This code is slow since it is not currently specialized for different formats
5328 
5329 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5330 @*/
5331 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5332 {
5333   Vec ones;
5334 
5335   PetscFunctionBegin;
5336   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5337   PetscValidType(mat, 1);
5338   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5339   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5340   MatCheckPreallocated(mat, 1);
5341   PetscCall(MatCreateVecs(mat, &ones, NULL));
5342   PetscCall(VecSet(ones, 1.));
5343   PetscCall(MatMult(mat, ones, v));
5344   PetscCall(VecDestroy(&ones));
5345   PetscFunctionReturn(PETSC_SUCCESS);
5346 }
5347 
5348 /*@
5349   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5350   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5351 
5352   Collective
5353 
5354   Input Parameter:
5355 . mat - the matrix to provide the transpose
5356 
5357   Output Parameter:
5358 . 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
5359 
5360   Level: advanced
5361 
5362   Note:
5363   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
5364   routine allows bypassing that call.
5365 
5366 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5367 @*/
5368 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5369 {
5370   MatParentState *rb = NULL;
5371 
5372   PetscFunctionBegin;
5373   PetscCall(PetscNew(&rb));
5374   rb->id    = ((PetscObject)mat)->id;
5375   rb->state = 0;
5376   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5377   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5378   PetscFunctionReturn(PETSC_SUCCESS);
5379 }
5380 
5381 /*@
5382   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5383 
5384   Collective
5385 
5386   Input Parameters:
5387 + mat   - the matrix to transpose
5388 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5389 
5390   Output Parameter:
5391 . B - the transpose of the matrix
5392 
5393   Level: intermediate
5394 
5395   Notes:
5396   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5397 
5398   `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
5399   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5400 
5401   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.
5402 
5403   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5404   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5405 
5406   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5407 
5408   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5409 
5410 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5411           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5412 @*/
5413 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5414 {
5415   PetscContainer  rB = NULL;
5416   MatParentState *rb = NULL;
5417 
5418   PetscFunctionBegin;
5419   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5420   PetscValidType(mat, 1);
5421   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5422   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5423   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5424   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5425   MatCheckPreallocated(mat, 1);
5426   if (reuse == MAT_REUSE_MATRIX) {
5427     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5428     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5429     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5430     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5431     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5432   }
5433 
5434   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5435   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5436     PetscUseTypeMethod(mat, transpose, reuse, B);
5437     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5438   }
5439   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5440 
5441   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5442   if (reuse != MAT_INPLACE_MATRIX) {
5443     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5444     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5445     rb->state        = ((PetscObject)mat)->state;
5446     rb->nonzerostate = mat->nonzerostate;
5447   }
5448   PetscFunctionReturn(PETSC_SUCCESS);
5449 }
5450 
5451 /*@
5452   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5453 
5454   Collective
5455 
5456   Input Parameter:
5457 . A - the matrix to transpose
5458 
5459   Output Parameter:
5460 . 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
5461       numerical portion.
5462 
5463   Level: intermediate
5464 
5465   Note:
5466   This is not supported for many matrix types, use `MatTranspose()` in those cases
5467 
5468 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5469 @*/
5470 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5471 {
5472   PetscFunctionBegin;
5473   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5474   PetscValidType(A, 1);
5475   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5476   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5477   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5478   PetscUseTypeMethod(A, transposesymbolic, B);
5479   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5480 
5481   PetscCall(MatTransposeSetPrecursor(A, *B));
5482   PetscFunctionReturn(PETSC_SUCCESS);
5483 }
5484 
5485 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5486 {
5487   PetscContainer  rB;
5488   MatParentState *rb;
5489 
5490   PetscFunctionBegin;
5491   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5492   PetscValidType(A, 1);
5493   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5494   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5495   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5496   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5497   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5498   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5499   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5500   PetscFunctionReturn(PETSC_SUCCESS);
5501 }
5502 
5503 /*@
5504   MatIsTranspose - Test whether a matrix is another one's transpose,
5505   or its own, in which case it tests symmetry.
5506 
5507   Collective
5508 
5509   Input Parameters:
5510 + A   - the matrix to test
5511 . B   - the matrix to test against, this can equal the first parameter
5512 - tol - tolerance, differences between entries smaller than this are counted as zero
5513 
5514   Output Parameter:
5515 . flg - the result
5516 
5517   Level: intermediate
5518 
5519   Notes:
5520   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5521   test involves parallel copies of the block off-diagonal parts of the matrix.
5522 
5523 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5524 @*/
5525 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5526 {
5527   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5528 
5529   PetscFunctionBegin;
5530   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5531   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5532   PetscAssertPointer(flg, 4);
5533   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5534   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5535   *flg = PETSC_FALSE;
5536   if (f && g) {
5537     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5538     PetscCall((*f)(A, B, tol, flg));
5539   } else {
5540     MatType mattype;
5541 
5542     PetscCall(MatGetType(f ? B : A, &mattype));
5543     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5544   }
5545   PetscFunctionReturn(PETSC_SUCCESS);
5546 }
5547 
5548 /*@
5549   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5550 
5551   Collective
5552 
5553   Input Parameters:
5554 + mat   - the matrix to transpose and complex conjugate
5555 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5556 
5557   Output Parameter:
5558 . B - the Hermitian transpose
5559 
5560   Level: intermediate
5561 
5562 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5563 @*/
5564 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5565 {
5566   PetscFunctionBegin;
5567   PetscCall(MatTranspose(mat, reuse, B));
5568 #if defined(PETSC_USE_COMPLEX)
5569   PetscCall(MatConjugate(*B));
5570 #endif
5571   PetscFunctionReturn(PETSC_SUCCESS);
5572 }
5573 
5574 /*@
5575   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5576 
5577   Collective
5578 
5579   Input Parameters:
5580 + A   - the matrix to test
5581 . B   - the matrix to test against, this can equal the first parameter
5582 - tol - tolerance, differences between entries smaller than this are counted as zero
5583 
5584   Output Parameter:
5585 . flg - the result
5586 
5587   Level: intermediate
5588 
5589   Notes:
5590   Only available for `MATAIJ` matrices.
5591 
5592   The sequential algorithm
5593   has a running time of the order of the number of nonzeros; the parallel
5594   test involves parallel copies of the block off-diagonal parts of the matrix.
5595 
5596 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5597 @*/
5598 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5599 {
5600   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5601 
5602   PetscFunctionBegin;
5603   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5604   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5605   PetscAssertPointer(flg, 4);
5606   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5607   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5608   if (f && g) {
5609     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5610     PetscCall((*f)(A, B, tol, flg));
5611   }
5612   PetscFunctionReturn(PETSC_SUCCESS);
5613 }
5614 
5615 /*@
5616   MatPermute - Creates a new matrix with rows and columns permuted from the
5617   original.
5618 
5619   Collective
5620 
5621   Input Parameters:
5622 + mat - the matrix to permute
5623 . row - row permutation, each processor supplies only the permutation for its rows
5624 - col - column permutation, each processor supplies only the permutation for its columns
5625 
5626   Output Parameter:
5627 . B - the permuted matrix
5628 
5629   Level: advanced
5630 
5631   Note:
5632   The index sets map from row/col of permuted matrix to row/col of original matrix.
5633   The index sets should be on the same communicator as mat and have the same local sizes.
5634 
5635   Developer Note:
5636   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5637   exploit the fact that row and col are permutations, consider implementing the
5638   more general `MatCreateSubMatrix()` instead.
5639 
5640 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5641 @*/
5642 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5643 {
5644   PetscFunctionBegin;
5645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5646   PetscValidType(mat, 1);
5647   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5648   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5649   PetscAssertPointer(B, 4);
5650   PetscCheckSameComm(mat, 1, row, 2);
5651   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5652   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5653   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5654   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5655   MatCheckPreallocated(mat, 1);
5656 
5657   if (mat->ops->permute) {
5658     PetscUseTypeMethod(mat, permute, row, col, B);
5659     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5660   } else {
5661     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5662   }
5663   PetscFunctionReturn(PETSC_SUCCESS);
5664 }
5665 
5666 /*@
5667   MatEqual - Compares two matrices.
5668 
5669   Collective
5670 
5671   Input Parameters:
5672 + A - the first matrix
5673 - B - the second matrix
5674 
5675   Output Parameter:
5676 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5677 
5678   Level: intermediate
5679 
5680 .seealso: [](ch_matrices), `Mat`
5681 @*/
5682 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5683 {
5684   PetscFunctionBegin;
5685   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5686   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5687   PetscValidType(A, 1);
5688   PetscValidType(B, 2);
5689   PetscAssertPointer(flg, 3);
5690   PetscCheckSameComm(A, 1, B, 2);
5691   MatCheckPreallocated(A, 1);
5692   MatCheckPreallocated(B, 2);
5693   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5694   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5695   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,
5696              B->cmap->N);
5697   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5698     PetscUseTypeMethod(A, equal, B, flg);
5699   } else {
5700     PetscCall(MatMultEqual(A, B, 10, flg));
5701   }
5702   PetscFunctionReturn(PETSC_SUCCESS);
5703 }
5704 
5705 /*@
5706   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5707   matrices that are stored as vectors.  Either of the two scaling
5708   matrices can be `NULL`.
5709 
5710   Collective
5711 
5712   Input Parameters:
5713 + mat - the matrix to be scaled
5714 . l   - the left scaling vector (or `NULL`)
5715 - r   - the right scaling vector (or `NULL`)
5716 
5717   Level: intermediate
5718 
5719   Note:
5720   `MatDiagonalScale()` computes $A = LAR$, where
5721   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5722   The L scales the rows of the matrix, the R scales the columns of the matrix.
5723 
5724 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5725 @*/
5726 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5727 {
5728   PetscFunctionBegin;
5729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5730   PetscValidType(mat, 1);
5731   if (l) {
5732     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5733     PetscCheckSameComm(mat, 1, l, 2);
5734   }
5735   if (r) {
5736     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5737     PetscCheckSameComm(mat, 1, r, 3);
5738   }
5739   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5740   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5741   MatCheckPreallocated(mat, 1);
5742   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5743 
5744   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5745   PetscUseTypeMethod(mat, diagonalscale, l, r);
5746   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5747   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5748   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5749   PetscFunctionReturn(PETSC_SUCCESS);
5750 }
5751 
5752 /*@
5753   MatScale - Scales all elements of a matrix by a given number.
5754 
5755   Logically Collective
5756 
5757   Input Parameters:
5758 + mat - the matrix to be scaled
5759 - a   - the scaling value
5760 
5761   Level: intermediate
5762 
5763 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5764 @*/
5765 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5766 {
5767   PetscFunctionBegin;
5768   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5769   PetscValidType(mat, 1);
5770   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5771   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5772   PetscValidLogicalCollectiveScalar(mat, a, 2);
5773   MatCheckPreallocated(mat, 1);
5774 
5775   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5776   if (a != (PetscScalar)1.0) {
5777     PetscUseTypeMethod(mat, scale, a);
5778     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5779   }
5780   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5781   PetscFunctionReturn(PETSC_SUCCESS);
5782 }
5783 
5784 /*@
5785   MatNorm - Calculates various norms of a matrix.
5786 
5787   Collective
5788 
5789   Input Parameters:
5790 + mat  - the matrix
5791 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5792 
5793   Output Parameter:
5794 . nrm - the resulting norm
5795 
5796   Level: intermediate
5797 
5798 .seealso: [](ch_matrices), `Mat`
5799 @*/
5800 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5801 {
5802   PetscFunctionBegin;
5803   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5804   PetscValidType(mat, 1);
5805   PetscAssertPointer(nrm, 3);
5806 
5807   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5808   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5809   MatCheckPreallocated(mat, 1);
5810 
5811   PetscUseTypeMethod(mat, norm, type, nrm);
5812   PetscFunctionReturn(PETSC_SUCCESS);
5813 }
5814 
5815 /*
5816      This variable is used to prevent counting of MatAssemblyBegin() that
5817    are called from within a MatAssemblyEnd().
5818 */
5819 static PetscInt MatAssemblyEnd_InUse = 0;
5820 /*@
5821   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5822   be called after completing all calls to `MatSetValues()`.
5823 
5824   Collective
5825 
5826   Input Parameters:
5827 + mat  - the matrix
5828 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5829 
5830   Level: beginner
5831 
5832   Notes:
5833   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5834   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5835 
5836   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5837   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5838   using the matrix.
5839 
5840   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5841   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
5842   a global collective operation requiring all processes that share the matrix.
5843 
5844   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5845   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5846   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5847 
5848 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5849 @*/
5850 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5851 {
5852   PetscFunctionBegin;
5853   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5854   PetscValidType(mat, 1);
5855   MatCheckPreallocated(mat, 1);
5856   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5857   if (mat->assembled) {
5858     mat->was_assembled = PETSC_TRUE;
5859     mat->assembled     = PETSC_FALSE;
5860   }
5861 
5862   if (!MatAssemblyEnd_InUse) {
5863     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5864     PetscTryTypeMethod(mat, assemblybegin, type);
5865     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5866   } else PetscTryTypeMethod(mat, assemblybegin, type);
5867   PetscFunctionReturn(PETSC_SUCCESS);
5868 }
5869 
5870 /*@
5871   MatAssembled - Indicates if a matrix has been assembled and is ready for
5872   use; for example, in matrix-vector product.
5873 
5874   Not Collective
5875 
5876   Input Parameter:
5877 . mat - the matrix
5878 
5879   Output Parameter:
5880 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5881 
5882   Level: advanced
5883 
5884 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5885 @*/
5886 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5887 {
5888   PetscFunctionBegin;
5889   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5890   PetscAssertPointer(assembled, 2);
5891   *assembled = mat->assembled;
5892   PetscFunctionReturn(PETSC_SUCCESS);
5893 }
5894 
5895 /*@
5896   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5897   be called after `MatAssemblyBegin()`.
5898 
5899   Collective
5900 
5901   Input Parameters:
5902 + mat  - the matrix
5903 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5904 
5905   Options Database Keys:
5906 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5907 . -mat_view ::ascii_info_detail      - Prints more detailed info
5908 . -mat_view                          - Prints matrix in ASCII format
5909 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5910 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5911 . -display <name>                    - Sets display name (default is host)
5912 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5913 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5914 . -viewer_socket_machine <machine>   - Machine to use for socket
5915 . -viewer_socket_port <port>         - Port number to use for socket
5916 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5917 
5918   Level: beginner
5919 
5920 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5921 @*/
5922 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5923 {
5924   static PetscInt inassm = 0;
5925   PetscBool       flg    = PETSC_FALSE;
5926 
5927   PetscFunctionBegin;
5928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5929   PetscValidType(mat, 1);
5930 
5931   inassm++;
5932   MatAssemblyEnd_InUse++;
5933   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5934     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5935     PetscTryTypeMethod(mat, assemblyend, type);
5936     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5937   } else PetscTryTypeMethod(mat, assemblyend, type);
5938 
5939   /* Flush assembly is not a true assembly */
5940   if (type != MAT_FLUSH_ASSEMBLY) {
5941     if (mat->num_ass) {
5942       if (!mat->symmetry_eternal) {
5943         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5944         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5945       }
5946       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5947       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5948     }
5949     mat->num_ass++;
5950     mat->assembled        = PETSC_TRUE;
5951     mat->ass_nonzerostate = mat->nonzerostate;
5952   }
5953 
5954   mat->insertmode = NOT_SET_VALUES;
5955   MatAssemblyEnd_InUse--;
5956   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5957   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5958     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5959 
5960     if (mat->checksymmetryonassembly) {
5961       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5962       if (flg) {
5963         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5964       } else {
5965         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5966       }
5967     }
5968     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5969   }
5970   inassm--;
5971   PetscFunctionReturn(PETSC_SUCCESS);
5972 }
5973 
5974 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5975 /*@
5976   MatSetOption - Sets a parameter option for a matrix. Some options
5977   may be specific to certain storage formats.  Some options
5978   determine how values will be inserted (or added). Sorted,
5979   row-oriented input will generally assemble the fastest. The default
5980   is row-oriented.
5981 
5982   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5983 
5984   Input Parameters:
5985 + mat - the matrix
5986 . op  - the option, one of those listed below (and possibly others),
5987 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5988 
5989   Options Describing Matrix Structure:
5990 + `MAT_SPD`                         - symmetric positive definite
5991 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5992 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5993 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5994 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5995 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5996 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5997 
5998    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5999    do not need to be computed (usually at a high cost)
6000 
6001    Options For Use with `MatSetValues()`:
6002    Insert a logically dense subblock, which can be
6003 . `MAT_ROW_ORIENTED`                - row-oriented (default)
6004 
6005    These options reflect the data you pass in with `MatSetValues()`; it has
6006    nothing to do with how the data is stored internally in the matrix
6007    data structure.
6008 
6009    When (re)assembling a matrix, we can restrict the input for
6010    efficiency/debugging purposes.  These options include
6011 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
6012 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
6013 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
6014 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
6015 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
6016 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
6017         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
6018         performance for very large process counts.
6019 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
6020         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
6021         functions, instead sending only neighbor messages.
6022 
6023   Level: intermediate
6024 
6025   Notes:
6026   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
6027 
6028   Some options are relevant only for particular matrix types and
6029   are thus ignored by others.  Other options are not supported by
6030   certain matrix types and will generate an error message if set.
6031 
6032   If using Fortran to compute a matrix, one may need to
6033   use the column-oriented option (or convert to the row-oriented
6034   format).
6035 
6036   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
6037   that would generate a new entry in the nonzero structure is instead
6038   ignored.  Thus, if memory has not already been allocated for this particular
6039   data, then the insertion is ignored. For dense matrices, in which
6040   the entire array is allocated, no entries are ever ignored.
6041   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6042 
6043   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6044   that would generate a new entry in the nonzero structure instead produces
6045   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
6046 
6047   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6048   that would generate a new entry that has not been preallocated will
6049   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6050   only.) This is a useful flag when debugging matrix memory preallocation.
6051   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6052 
6053   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6054   other processors should be dropped, rather than stashed.
6055   This is useful if you know that the "owning" processor is also
6056   always generating the correct matrix entries, so that PETSc need
6057   not transfer duplicate entries generated on another processor.
6058 
6059   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6060   searches during matrix assembly. When this flag is set, the hash table
6061   is created during the first matrix assembly. This hash table is
6062   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6063   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6064   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6065   supported by `MATMPIBAIJ` format only.
6066 
6067   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6068   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6069 
6070   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6071   a zero location in the matrix
6072 
6073   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6074 
6075   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6076   zero row routines and thus improves performance for very large process counts.
6077 
6078   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6079   part of the matrix (since they should match the upper triangular part).
6080 
6081   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6082   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6083   with finite difference schemes with non-periodic boundary conditions.
6084 
6085   Developer Note:
6086   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6087   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6088   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6089   not changed.
6090 
6091 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6092 @*/
6093 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6094 {
6095   PetscFunctionBegin;
6096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6097   if (op > 0) {
6098     PetscValidLogicalCollectiveEnum(mat, op, 2);
6099     PetscValidLogicalCollectiveBool(mat, flg, 3);
6100   }
6101 
6102   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);
6103 
6104   switch (op) {
6105   case MAT_FORCE_DIAGONAL_ENTRIES:
6106     mat->force_diagonals = flg;
6107     PetscFunctionReturn(PETSC_SUCCESS);
6108   case MAT_NO_OFF_PROC_ENTRIES:
6109     mat->nooffprocentries = flg;
6110     PetscFunctionReturn(PETSC_SUCCESS);
6111   case MAT_SUBSET_OFF_PROC_ENTRIES:
6112     mat->assembly_subset = flg;
6113     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6114 #if !defined(PETSC_HAVE_MPIUNI)
6115       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6116 #endif
6117       mat->stash.first_assembly_done = PETSC_FALSE;
6118     }
6119     PetscFunctionReturn(PETSC_SUCCESS);
6120   case MAT_NO_OFF_PROC_ZERO_ROWS:
6121     mat->nooffproczerorows = flg;
6122     PetscFunctionReturn(PETSC_SUCCESS);
6123   case MAT_SPD:
6124     if (flg) {
6125       mat->spd                    = PETSC_BOOL3_TRUE;
6126       mat->symmetric              = PETSC_BOOL3_TRUE;
6127       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6128     } else {
6129       mat->spd = PETSC_BOOL3_FALSE;
6130     }
6131     break;
6132   case MAT_SYMMETRIC:
6133     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6134     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6135 #if !defined(PETSC_USE_COMPLEX)
6136     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6137 #endif
6138     break;
6139   case MAT_HERMITIAN:
6140     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6141     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6142 #if !defined(PETSC_USE_COMPLEX)
6143     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6144 #endif
6145     break;
6146   case MAT_STRUCTURALLY_SYMMETRIC:
6147     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6148     break;
6149   case MAT_SYMMETRY_ETERNAL:
6150     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");
6151     mat->symmetry_eternal = flg;
6152     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6153     break;
6154   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6155     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");
6156     mat->structural_symmetry_eternal = flg;
6157     break;
6158   case MAT_SPD_ETERNAL:
6159     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");
6160     mat->spd_eternal = flg;
6161     if (flg) {
6162       mat->structural_symmetry_eternal = PETSC_TRUE;
6163       mat->symmetry_eternal            = PETSC_TRUE;
6164     }
6165     break;
6166   case MAT_STRUCTURE_ONLY:
6167     mat->structure_only = flg;
6168     break;
6169   case MAT_SORTED_FULL:
6170     mat->sortedfull = flg;
6171     break;
6172   default:
6173     break;
6174   }
6175   PetscTryTypeMethod(mat, setoption, op, flg);
6176   PetscFunctionReturn(PETSC_SUCCESS);
6177 }
6178 
6179 /*@
6180   MatGetOption - Gets a parameter option that has been set for a matrix.
6181 
6182   Logically Collective
6183 
6184   Input Parameters:
6185 + mat - the matrix
6186 - op  - the option, this only responds to certain options, check the code for which ones
6187 
6188   Output Parameter:
6189 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6190 
6191   Level: intermediate
6192 
6193   Notes:
6194   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6195 
6196   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6197   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6198 
6199 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6200     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6201 @*/
6202 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6203 {
6204   PetscFunctionBegin;
6205   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6206   PetscValidType(mat, 1);
6207 
6208   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);
6209   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()");
6210 
6211   switch (op) {
6212   case MAT_NO_OFF_PROC_ENTRIES:
6213     *flg = mat->nooffprocentries;
6214     break;
6215   case MAT_NO_OFF_PROC_ZERO_ROWS:
6216     *flg = mat->nooffproczerorows;
6217     break;
6218   case MAT_SYMMETRIC:
6219     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6220     break;
6221   case MAT_HERMITIAN:
6222     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6223     break;
6224   case MAT_STRUCTURALLY_SYMMETRIC:
6225     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6226     break;
6227   case MAT_SPD:
6228     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6229     break;
6230   case MAT_SYMMETRY_ETERNAL:
6231     *flg = mat->symmetry_eternal;
6232     break;
6233   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6234     *flg = mat->symmetry_eternal;
6235     break;
6236   default:
6237     break;
6238   }
6239   PetscFunctionReturn(PETSC_SUCCESS);
6240 }
6241 
6242 /*@
6243   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6244   this routine retains the old nonzero structure.
6245 
6246   Logically Collective
6247 
6248   Input Parameter:
6249 . mat - the matrix
6250 
6251   Level: intermediate
6252 
6253   Note:
6254   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.
6255   See the Performance chapter of the users manual for information on preallocating matrices.
6256 
6257 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6258 @*/
6259 PetscErrorCode MatZeroEntries(Mat mat)
6260 {
6261   PetscFunctionBegin;
6262   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6263   PetscValidType(mat, 1);
6264   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6265   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");
6266   MatCheckPreallocated(mat, 1);
6267 
6268   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6269   PetscUseTypeMethod(mat, zeroentries);
6270   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6271   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6272   PetscFunctionReturn(PETSC_SUCCESS);
6273 }
6274 
6275 /*@
6276   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6277   of a set of rows and columns of a matrix.
6278 
6279   Collective
6280 
6281   Input Parameters:
6282 + mat     - the matrix
6283 . numRows - the number of rows/columns to zero
6284 . rows    - the global row indices
6285 . diag    - value put in the diagonal of the eliminated rows
6286 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6287 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6288 
6289   Level: intermediate
6290 
6291   Notes:
6292   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6293 
6294   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6295   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
6296 
6297   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6298   Krylov method to take advantage of the known solution on the zeroed rows.
6299 
6300   For the parallel case, all processes that share the matrix (i.e.,
6301   those in the communicator used for matrix creation) MUST call this
6302   routine, regardless of whether any rows being zeroed are owned by
6303   them.
6304 
6305   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6306   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
6307   missing.
6308 
6309   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6310   list only rows local to itself).
6311 
6312   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6313 
6314 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6315           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6316 @*/
6317 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6318 {
6319   PetscFunctionBegin;
6320   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6321   PetscValidType(mat, 1);
6322   if (numRows) PetscAssertPointer(rows, 3);
6323   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6324   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6325   MatCheckPreallocated(mat, 1);
6326 
6327   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6328   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6329   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6330   PetscFunctionReturn(PETSC_SUCCESS);
6331 }
6332 
6333 /*@
6334   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6335   of a set of rows and columns of a matrix.
6336 
6337   Collective
6338 
6339   Input Parameters:
6340 + mat  - the matrix
6341 . is   - the rows to zero
6342 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6343 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6344 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6345 
6346   Level: intermediate
6347 
6348   Note:
6349   See `MatZeroRowsColumns()` for details on how this routine operates.
6350 
6351 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6352           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6353 @*/
6354 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6355 {
6356   PetscInt        numRows;
6357   const PetscInt *rows;
6358 
6359   PetscFunctionBegin;
6360   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6361   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6362   PetscValidType(mat, 1);
6363   PetscValidType(is, 2);
6364   PetscCall(ISGetLocalSize(is, &numRows));
6365   PetscCall(ISGetIndices(is, &rows));
6366   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6367   PetscCall(ISRestoreIndices(is, &rows));
6368   PetscFunctionReturn(PETSC_SUCCESS);
6369 }
6370 
6371 /*@
6372   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6373   of a set of rows of a matrix.
6374 
6375   Collective
6376 
6377   Input Parameters:
6378 + mat     - the matrix
6379 . numRows - the number of rows to zero
6380 . rows    - the global row indices
6381 . diag    - value put in the diagonal of the zeroed rows
6382 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6383 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6384 
6385   Level: intermediate
6386 
6387   Notes:
6388   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6389 
6390   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6391 
6392   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6393   Krylov method to take advantage of the known solution on the zeroed rows.
6394 
6395   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)
6396   from the matrix.
6397 
6398   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6399   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6400   formats this does not alter the nonzero structure.
6401 
6402   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6403   of the matrix is not changed the values are
6404   merely zeroed.
6405 
6406   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6407   formats can optionally remove the main diagonal entry from the
6408   nonzero structure as well, by passing 0.0 as the final argument).
6409 
6410   For the parallel case, all processes that share the matrix (i.e.,
6411   those in the communicator used for matrix creation) MUST call this
6412   routine, regardless of whether any rows being zeroed are owned by
6413   them.
6414 
6415   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6416   list only rows local to itself).
6417 
6418   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6419   owns that are to be zeroed. This saves a global synchronization in the implementation.
6420 
6421 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6422           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6423 @*/
6424 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6425 {
6426   PetscFunctionBegin;
6427   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6428   PetscValidType(mat, 1);
6429   if (numRows) PetscAssertPointer(rows, 3);
6430   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6431   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6432   MatCheckPreallocated(mat, 1);
6433 
6434   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6435   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6436   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6437   PetscFunctionReturn(PETSC_SUCCESS);
6438 }
6439 
6440 /*@
6441   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6442   of a set of rows of a matrix indicated by an `IS`
6443 
6444   Collective
6445 
6446   Input Parameters:
6447 + mat  - the matrix
6448 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6449 . diag - value put in all diagonals of eliminated rows
6450 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6451 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6452 
6453   Level: intermediate
6454 
6455   Note:
6456   See `MatZeroRows()` for details on how this routine operates.
6457 
6458 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6459           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6460 @*/
6461 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6462 {
6463   PetscInt        numRows = 0;
6464   const PetscInt *rows    = NULL;
6465 
6466   PetscFunctionBegin;
6467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6468   PetscValidType(mat, 1);
6469   if (is) {
6470     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6471     PetscCall(ISGetLocalSize(is, &numRows));
6472     PetscCall(ISGetIndices(is, &rows));
6473   }
6474   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6475   if (is) PetscCall(ISRestoreIndices(is, &rows));
6476   PetscFunctionReturn(PETSC_SUCCESS);
6477 }
6478 
6479 /*@
6480   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6481   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6482 
6483   Collective
6484 
6485   Input Parameters:
6486 + mat     - the matrix
6487 . numRows - the number of rows to remove
6488 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6489 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6490 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6491 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6492 
6493   Level: intermediate
6494 
6495   Notes:
6496   See `MatZeroRows()` for details on how this routine operates.
6497 
6498   The grid coordinates are across the entire grid, not just the local portion
6499 
6500   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6501   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6502   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6503   `DM_BOUNDARY_PERIODIC` boundary type.
6504 
6505   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
6506   a single value per point) you can skip filling those indices.
6507 
6508   Fortran Note:
6509   `idxm` and `idxn` should be declared as
6510 $     MatStencil idxm(4, m)
6511   and the values inserted using
6512 .vb
6513     idxm(MatStencil_i, 1) = i
6514     idxm(MatStencil_j, 1) = j
6515     idxm(MatStencil_k, 1) = k
6516     idxm(MatStencil_c, 1) = c
6517    etc
6518 .ve
6519 
6520 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6521           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6522 @*/
6523 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6524 {
6525   PetscInt  dim    = mat->stencil.dim;
6526   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6527   PetscInt *dims   = mat->stencil.dims + 1;
6528   PetscInt *starts = mat->stencil.starts;
6529   PetscInt *dxm    = (PetscInt *)rows;
6530   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6531 
6532   PetscFunctionBegin;
6533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6534   PetscValidType(mat, 1);
6535   if (numRows) PetscAssertPointer(rows, 3);
6536 
6537   PetscCall(PetscMalloc1(numRows, &jdxm));
6538   for (i = 0; i < numRows; ++i) {
6539     /* Skip unused dimensions (they are ordered k, j, i, c) */
6540     for (j = 0; j < 3 - sdim; ++j) dxm++;
6541     /* Local index in X dir */
6542     tmp = *dxm++ - starts[0];
6543     /* Loop over remaining dimensions */
6544     for (j = 0; j < dim - 1; ++j) {
6545       /* If nonlocal, set index to be negative */
6546       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6547       /* Update local index */
6548       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6549     }
6550     /* Skip component slot if necessary */
6551     if (mat->stencil.noc) dxm++;
6552     /* Local row number */
6553     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6554   }
6555   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6556   PetscCall(PetscFree(jdxm));
6557   PetscFunctionReturn(PETSC_SUCCESS);
6558 }
6559 
6560 /*@
6561   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6562   of a set of rows and columns of a matrix.
6563 
6564   Collective
6565 
6566   Input Parameters:
6567 + mat     - the matrix
6568 . numRows - the number of rows/columns to remove
6569 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6570 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6571 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6572 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6573 
6574   Level: intermediate
6575 
6576   Notes:
6577   See `MatZeroRowsColumns()` for details on how this routine operates.
6578 
6579   The grid coordinates are across the entire grid, not just the local portion
6580 
6581   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6582   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6583   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6584   `DM_BOUNDARY_PERIODIC` boundary type.
6585 
6586   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
6587   a single value per point) you can skip filling those indices.
6588 
6589   Fortran Note:
6590   `idxm` and `idxn` should be declared as
6591 $     MatStencil idxm(4, m)
6592   and the values inserted using
6593 .vb
6594     idxm(MatStencil_i, 1) = i
6595     idxm(MatStencil_j, 1) = j
6596     idxm(MatStencil_k, 1) = k
6597     idxm(MatStencil_c, 1) = c
6598     etc
6599 .ve
6600 
6601 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6602           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6603 @*/
6604 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6605 {
6606   PetscInt  dim    = mat->stencil.dim;
6607   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6608   PetscInt *dims   = mat->stencil.dims + 1;
6609   PetscInt *starts = mat->stencil.starts;
6610   PetscInt *dxm    = (PetscInt *)rows;
6611   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6612 
6613   PetscFunctionBegin;
6614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6615   PetscValidType(mat, 1);
6616   if (numRows) PetscAssertPointer(rows, 3);
6617 
6618   PetscCall(PetscMalloc1(numRows, &jdxm));
6619   for (i = 0; i < numRows; ++i) {
6620     /* Skip unused dimensions (they are ordered k, j, i, c) */
6621     for (j = 0; j < 3 - sdim; ++j) dxm++;
6622     /* Local index in X dir */
6623     tmp = *dxm++ - starts[0];
6624     /* Loop over remaining dimensions */
6625     for (j = 0; j < dim - 1; ++j) {
6626       /* If nonlocal, set index to be negative */
6627       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6628       /* Update local index */
6629       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6630     }
6631     /* Skip component slot if necessary */
6632     if (mat->stencil.noc) dxm++;
6633     /* Local row number */
6634     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6635   }
6636   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6637   PetscCall(PetscFree(jdxm));
6638   PetscFunctionReturn(PETSC_SUCCESS);
6639 }
6640 
6641 /*@
6642   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6643   of a set of rows of a matrix; using local numbering of rows.
6644 
6645   Collective
6646 
6647   Input Parameters:
6648 + mat     - the matrix
6649 . numRows - the number of rows to remove
6650 . rows    - the local row indices
6651 . diag    - value put in all diagonals of eliminated rows
6652 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6653 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6654 
6655   Level: intermediate
6656 
6657   Notes:
6658   Before calling `MatZeroRowsLocal()`, the user must first set the
6659   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6660 
6661   See `MatZeroRows()` for details on how this routine operates.
6662 
6663 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6664           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6665 @*/
6666 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6667 {
6668   PetscFunctionBegin;
6669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6670   PetscValidType(mat, 1);
6671   if (numRows) PetscAssertPointer(rows, 3);
6672   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6673   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6674   MatCheckPreallocated(mat, 1);
6675 
6676   if (mat->ops->zerorowslocal) {
6677     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6678   } else {
6679     IS              is, newis;
6680     const PetscInt *newRows;
6681 
6682     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6683     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6684     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6685     PetscCall(ISGetIndices(newis, &newRows));
6686     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6687     PetscCall(ISRestoreIndices(newis, &newRows));
6688     PetscCall(ISDestroy(&newis));
6689     PetscCall(ISDestroy(&is));
6690   }
6691   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6692   PetscFunctionReturn(PETSC_SUCCESS);
6693 }
6694 
6695 /*@
6696   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6697   of a set of rows of a matrix; using local numbering of rows.
6698 
6699   Collective
6700 
6701   Input Parameters:
6702 + mat  - the matrix
6703 . is   - index set of rows to remove
6704 . diag - value put in all diagonals of eliminated rows
6705 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6706 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6707 
6708   Level: intermediate
6709 
6710   Notes:
6711   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6712   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6713 
6714   See `MatZeroRows()` for details on how this routine operates.
6715 
6716 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6717           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6718 @*/
6719 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6720 {
6721   PetscInt        numRows;
6722   const PetscInt *rows;
6723 
6724   PetscFunctionBegin;
6725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6726   PetscValidType(mat, 1);
6727   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6728   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6729   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6730   MatCheckPreallocated(mat, 1);
6731 
6732   PetscCall(ISGetLocalSize(is, &numRows));
6733   PetscCall(ISGetIndices(is, &rows));
6734   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6735   PetscCall(ISRestoreIndices(is, &rows));
6736   PetscFunctionReturn(PETSC_SUCCESS);
6737 }
6738 
6739 /*@
6740   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6741   of a set of rows and columns of a matrix; using local numbering of rows.
6742 
6743   Collective
6744 
6745   Input Parameters:
6746 + mat     - the matrix
6747 . numRows - the number of rows to remove
6748 . rows    - the global row indices
6749 . diag    - value put in all diagonals of eliminated rows
6750 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6751 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6752 
6753   Level: intermediate
6754 
6755   Notes:
6756   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6757   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6758 
6759   See `MatZeroRowsColumns()` for details on how this routine operates.
6760 
6761 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6762           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6763 @*/
6764 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6765 {
6766   IS              is, newis;
6767   const PetscInt *newRows;
6768 
6769   PetscFunctionBegin;
6770   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6771   PetscValidType(mat, 1);
6772   if (numRows) PetscAssertPointer(rows, 3);
6773   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6774   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6775   MatCheckPreallocated(mat, 1);
6776 
6777   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6778   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6779   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6780   PetscCall(ISGetIndices(newis, &newRows));
6781   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6782   PetscCall(ISRestoreIndices(newis, &newRows));
6783   PetscCall(ISDestroy(&newis));
6784   PetscCall(ISDestroy(&is));
6785   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6786   PetscFunctionReturn(PETSC_SUCCESS);
6787 }
6788 
6789 /*@
6790   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6791   of a set of rows and columns of a matrix; using local numbering of rows.
6792 
6793   Collective
6794 
6795   Input Parameters:
6796 + mat  - the matrix
6797 . is   - index set of rows to remove
6798 . diag - value put in all diagonals of eliminated rows
6799 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6800 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6801 
6802   Level: intermediate
6803 
6804   Notes:
6805   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6806   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6807 
6808   See `MatZeroRowsColumns()` for details on how this routine operates.
6809 
6810 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6811           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6812 @*/
6813 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6814 {
6815   PetscInt        numRows;
6816   const PetscInt *rows;
6817 
6818   PetscFunctionBegin;
6819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6820   PetscValidType(mat, 1);
6821   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6822   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6823   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6824   MatCheckPreallocated(mat, 1);
6825 
6826   PetscCall(ISGetLocalSize(is, &numRows));
6827   PetscCall(ISGetIndices(is, &rows));
6828   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6829   PetscCall(ISRestoreIndices(is, &rows));
6830   PetscFunctionReturn(PETSC_SUCCESS);
6831 }
6832 
6833 /*@
6834   MatGetSize - Returns the numbers of rows and columns in a matrix.
6835 
6836   Not Collective
6837 
6838   Input Parameter:
6839 . mat - the matrix
6840 
6841   Output Parameters:
6842 + m - the number of global rows
6843 - n - the number of global columns
6844 
6845   Level: beginner
6846 
6847   Note:
6848   Both output parameters can be `NULL` on input.
6849 
6850 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6851 @*/
6852 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6853 {
6854   PetscFunctionBegin;
6855   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6856   if (m) *m = mat->rmap->N;
6857   if (n) *n = mat->cmap->N;
6858   PetscFunctionReturn(PETSC_SUCCESS);
6859 }
6860 
6861 /*@
6862   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6863   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6864 
6865   Not Collective
6866 
6867   Input Parameter:
6868 . mat - the matrix
6869 
6870   Output Parameters:
6871 + m - the number of local rows, use `NULL` to not obtain this value
6872 - n - the number of local columns, use `NULL` to not obtain this value
6873 
6874   Level: beginner
6875 
6876 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6877 @*/
6878 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6879 {
6880   PetscFunctionBegin;
6881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6882   if (m) PetscAssertPointer(m, 2);
6883   if (n) PetscAssertPointer(n, 3);
6884   if (m) *m = mat->rmap->n;
6885   if (n) *n = mat->cmap->n;
6886   PetscFunctionReturn(PETSC_SUCCESS);
6887 }
6888 
6889 /*@
6890   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6891   vector one multiplies this matrix by that are owned by this processor.
6892 
6893   Not Collective, unless matrix has not been allocated, then collective
6894 
6895   Input Parameter:
6896 . mat - the matrix
6897 
6898   Output Parameters:
6899 + m - the global index of the first local column, use `NULL` to not obtain this value
6900 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6901 
6902   Level: developer
6903 
6904   Notes:
6905   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6906 
6907   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6908   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6909 
6910   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6911   the local values in the matrix.
6912 
6913   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6914   Layouts](sec_matlayout) for details on matrix layouts.
6915 
6916 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6917           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6918 @*/
6919 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6920 {
6921   PetscFunctionBegin;
6922   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6923   PetscValidType(mat, 1);
6924   if (m) PetscAssertPointer(m, 2);
6925   if (n) PetscAssertPointer(n, 3);
6926   MatCheckPreallocated(mat, 1);
6927   if (m) *m = mat->cmap->rstart;
6928   if (n) *n = mat->cmap->rend;
6929   PetscFunctionReturn(PETSC_SUCCESS);
6930 }
6931 
6932 /*@
6933   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6934   this MPI process.
6935 
6936   Not Collective
6937 
6938   Input Parameter:
6939 . mat - the matrix
6940 
6941   Output Parameters:
6942 + m - the global index of the first local row, use `NULL` to not obtain this value
6943 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6944 
6945   Level: beginner
6946 
6947   Notes:
6948   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6949 
6950   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6951   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6952 
6953   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6954   the local values in the matrix.
6955 
6956   The high argument is one more than the last element stored locally.
6957 
6958   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6959   would contain the result of a matrix vector product with this matrix. See [Matrix
6960   Layouts](sec_matlayout) for details on matrix layouts.
6961 
6962 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6963           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6964 @*/
6965 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6966 {
6967   PetscFunctionBegin;
6968   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6969   PetscValidType(mat, 1);
6970   if (m) PetscAssertPointer(m, 2);
6971   if (n) PetscAssertPointer(n, 3);
6972   MatCheckPreallocated(mat, 1);
6973   if (m) *m = mat->rmap->rstart;
6974   if (n) *n = mat->rmap->rend;
6975   PetscFunctionReturn(PETSC_SUCCESS);
6976 }
6977 
6978 /*@C
6979   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6980   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6981 
6982   Not Collective, unless matrix has not been allocated
6983 
6984   Input Parameter:
6985 . mat - the matrix
6986 
6987   Output Parameter:
6988 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6989            where `size` is the number of MPI processes used by `mat`
6990 
6991   Level: beginner
6992 
6993   Notes:
6994   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6995 
6996   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6997   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6998 
6999   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7000   the local values in the matrix.
7001 
7002   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
7003   would contain the result of a matrix vector product with this matrix. See [Matrix
7004   Layouts](sec_matlayout) for details on matrix layouts.
7005 
7006 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
7007           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
7008           `DMDAGetGhostCorners()`, `DM`
7009 @*/
7010 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
7011 {
7012   PetscFunctionBegin;
7013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7014   PetscValidType(mat, 1);
7015   MatCheckPreallocated(mat, 1);
7016   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
7017   PetscFunctionReturn(PETSC_SUCCESS);
7018 }
7019 
7020 /*@C
7021   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
7022   vector one multiplies this vector by that are owned by each processor.
7023 
7024   Not Collective, unless matrix has not been allocated
7025 
7026   Input Parameter:
7027 . mat - the matrix
7028 
7029   Output Parameter:
7030 . ranges - start of each processors portion plus one more than the total length at the end
7031 
7032   Level: beginner
7033 
7034   Notes:
7035   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
7036 
7037   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7038   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7039 
7040   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7041   the local values in the matrix.
7042 
7043   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7044   Layouts](sec_matlayout) for details on matrix layouts.
7045 
7046 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7047           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7048           `DMDAGetGhostCorners()`, `DM`
7049 @*/
7050 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7051 {
7052   PetscFunctionBegin;
7053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7054   PetscValidType(mat, 1);
7055   MatCheckPreallocated(mat, 1);
7056   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7057   PetscFunctionReturn(PETSC_SUCCESS);
7058 }
7059 
7060 /*@
7061   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7062 
7063   Not Collective
7064 
7065   Input Parameter:
7066 . A - matrix
7067 
7068   Output Parameters:
7069 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7070 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7071 
7072   Level: intermediate
7073 
7074   Note:
7075   You should call `ISDestroy()` on the returned `IS`
7076 
7077   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7078   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7079   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7080   details on matrix layouts.
7081 
7082 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7083 @*/
7084 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7085 {
7086   PetscErrorCode (*f)(Mat, IS *, IS *);
7087 
7088   PetscFunctionBegin;
7089   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7090   PetscValidType(A, 1);
7091   MatCheckPreallocated(A, 1);
7092   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7093   if (f) {
7094     PetscCall((*f)(A, rows, cols));
7095   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7096     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7097     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7098   }
7099   PetscFunctionReturn(PETSC_SUCCESS);
7100 }
7101 
7102 /*@
7103   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7104   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7105   to complete the factorization.
7106 
7107   Collective
7108 
7109   Input Parameters:
7110 + fact - the factorized matrix obtained with `MatGetFactor()`
7111 . mat  - the matrix
7112 . row  - row permutation
7113 . col  - column permutation
7114 - info - structure containing
7115 .vb
7116       levels - number of levels of fill.
7117       expected fill - as ratio of original fill.
7118       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7119                 missing diagonal entries)
7120 .ve
7121 
7122   Level: developer
7123 
7124   Notes:
7125   See [Matrix Factorization](sec_matfactor) for additional information.
7126 
7127   Most users should employ the `KSP` interface for linear solvers
7128   instead of working directly with matrix algebra routines such as this.
7129   See, e.g., `KSPCreate()`.
7130 
7131   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7132 
7133   Developer Note:
7134   The Fortran interface is not autogenerated as the
7135   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7136 
7137 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7138           `MatGetOrdering()`, `MatFactorInfo`
7139 @*/
7140 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7141 {
7142   PetscFunctionBegin;
7143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7144   PetscValidType(mat, 2);
7145   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7146   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7147   PetscAssertPointer(info, 5);
7148   PetscAssertPointer(fact, 1);
7149   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7150   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7151   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7152   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7153   MatCheckPreallocated(mat, 2);
7154 
7155   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7156   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7157   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7158   PetscFunctionReturn(PETSC_SUCCESS);
7159 }
7160 
7161 /*@
7162   MatICCFactorSymbolic - Performs symbolic incomplete
7163   Cholesky factorization for a symmetric matrix.  Use
7164   `MatCholeskyFactorNumeric()` to complete the factorization.
7165 
7166   Collective
7167 
7168   Input Parameters:
7169 + fact - the factorized matrix obtained with `MatGetFactor()`
7170 . mat  - the matrix to be factored
7171 . perm - row and column permutation
7172 - info - structure containing
7173 .vb
7174       levels - number of levels of fill.
7175       expected fill - as ratio of original fill.
7176 .ve
7177 
7178   Level: developer
7179 
7180   Notes:
7181   Most users should employ the `KSP` interface for linear solvers
7182   instead of working directly with matrix algebra routines such as this.
7183   See, e.g., `KSPCreate()`.
7184 
7185   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7186 
7187   Developer Note:
7188   The Fortran interface is not autogenerated as the
7189   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7190 
7191 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7192 @*/
7193 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7194 {
7195   PetscFunctionBegin;
7196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7197   PetscValidType(mat, 2);
7198   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7199   PetscAssertPointer(info, 4);
7200   PetscAssertPointer(fact, 1);
7201   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7202   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7203   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7204   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7205   MatCheckPreallocated(mat, 2);
7206 
7207   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7208   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7209   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7210   PetscFunctionReturn(PETSC_SUCCESS);
7211 }
7212 
7213 /*@C
7214   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7215   points to an array of valid matrices, they may be reused to store the new
7216   submatrices.
7217 
7218   Collective
7219 
7220   Input Parameters:
7221 + mat   - the matrix
7222 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7223 . irow  - index set of rows to extract
7224 . icol  - index set of columns to extract
7225 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7226 
7227   Output Parameter:
7228 . submat - the array of submatrices
7229 
7230   Level: advanced
7231 
7232   Notes:
7233   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7234   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7235   to extract a parallel submatrix.
7236 
7237   Some matrix types place restrictions on the row and column
7238   indices, such as that they be sorted or that they be equal to each other.
7239 
7240   The index sets may not have duplicate entries.
7241 
7242   When extracting submatrices from a parallel matrix, each processor can
7243   form a different submatrix by setting the rows and columns of its
7244   individual index sets according to the local submatrix desired.
7245 
7246   When finished using the submatrices, the user should destroy
7247   them with `MatDestroySubMatrices()`.
7248 
7249   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7250   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7251 
7252   This routine creates the matrices in submat; you should NOT create them before
7253   calling it. It also allocates the array of matrix pointers submat.
7254 
7255   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7256   request one row/column in a block, they must request all rows/columns that are in
7257   that block. For example, if the block size is 2 you cannot request just row 0 and
7258   column 0.
7259 
7260   Fortran Note:
7261   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7262 
7263 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7264 @*/
7265 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7266 {
7267   PetscInt  i;
7268   PetscBool eq;
7269 
7270   PetscFunctionBegin;
7271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7272   PetscValidType(mat, 1);
7273   if (n) {
7274     PetscAssertPointer(irow, 3);
7275     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7276     PetscAssertPointer(icol, 4);
7277     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7278   }
7279   PetscAssertPointer(submat, 6);
7280   if (n && scall == MAT_REUSE_MATRIX) {
7281     PetscAssertPointer(*submat, 6);
7282     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7283   }
7284   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7285   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7286   MatCheckPreallocated(mat, 1);
7287   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7288   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7289   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7290   for (i = 0; i < n; i++) {
7291     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7292     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7293     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7294 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7295     if (mat->boundtocpu && mat->bindingpropagates) {
7296       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7297       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7298     }
7299 #endif
7300   }
7301   PetscFunctionReturn(PETSC_SUCCESS);
7302 }
7303 
7304 /*@C
7305   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7306 
7307   Collective
7308 
7309   Input Parameters:
7310 + mat   - the matrix
7311 . n     - the number of submatrixes to be extracted
7312 . irow  - index set of rows to extract
7313 . icol  - index set of columns to extract
7314 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7315 
7316   Output Parameter:
7317 . submat - the array of submatrices
7318 
7319   Level: advanced
7320 
7321   Note:
7322   This is used by `PCGASM`
7323 
7324 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7325 @*/
7326 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7327 {
7328   PetscInt  i;
7329   PetscBool eq;
7330 
7331   PetscFunctionBegin;
7332   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7333   PetscValidType(mat, 1);
7334   if (n) {
7335     PetscAssertPointer(irow, 3);
7336     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7337     PetscAssertPointer(icol, 4);
7338     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7339   }
7340   PetscAssertPointer(submat, 6);
7341   if (n && scall == MAT_REUSE_MATRIX) {
7342     PetscAssertPointer(*submat, 6);
7343     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7344   }
7345   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7346   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7347   MatCheckPreallocated(mat, 1);
7348 
7349   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7350   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7351   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7352   for (i = 0; i < n; i++) {
7353     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7354     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7355   }
7356   PetscFunctionReturn(PETSC_SUCCESS);
7357 }
7358 
7359 /*@C
7360   MatDestroyMatrices - Destroys an array of matrices.
7361 
7362   Collective
7363 
7364   Input Parameters:
7365 + n   - the number of local matrices
7366 - mat - the matrices (this is a pointer to the array of matrices)
7367 
7368   Level: advanced
7369 
7370   Notes:
7371   Frees not only the matrices, but also the array that contains the matrices
7372 
7373   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7374 
7375   Fortran Note:
7376   Does not free the `mat` array.
7377 
7378 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7379 @*/
7380 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7381 {
7382   PetscInt i;
7383 
7384   PetscFunctionBegin;
7385   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7386   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7387   PetscAssertPointer(mat, 2);
7388 
7389   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7390 
7391   /* memory is allocated even if n = 0 */
7392   PetscCall(PetscFree(*mat));
7393   PetscFunctionReturn(PETSC_SUCCESS);
7394 }
7395 
7396 /*@C
7397   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7398 
7399   Collective
7400 
7401   Input Parameters:
7402 + n   - the number of local matrices
7403 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7404                        sequence of `MatCreateSubMatrices()`)
7405 
7406   Level: advanced
7407 
7408   Note:
7409   Frees not only the matrices, but also the array that contains the matrices
7410 
7411   Fortran Note:
7412   Does not free the `mat` array.
7413 
7414 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7415 @*/
7416 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7417 {
7418   Mat mat0;
7419 
7420   PetscFunctionBegin;
7421   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7422   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7423   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7424   PetscAssertPointer(mat, 2);
7425 
7426   mat0 = (*mat)[0];
7427   if (mat0 && mat0->ops->destroysubmatrices) {
7428     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7429   } else {
7430     PetscCall(MatDestroyMatrices(n, mat));
7431   }
7432   PetscFunctionReturn(PETSC_SUCCESS);
7433 }
7434 
7435 /*@
7436   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7437 
7438   Collective
7439 
7440   Input Parameter:
7441 . mat - the matrix
7442 
7443   Output Parameter:
7444 . matstruct - the sequential matrix with the nonzero structure of `mat`
7445 
7446   Level: developer
7447 
7448 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7449 @*/
7450 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7451 {
7452   PetscFunctionBegin;
7453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7454   PetscAssertPointer(matstruct, 2);
7455 
7456   PetscValidType(mat, 1);
7457   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7458   MatCheckPreallocated(mat, 1);
7459 
7460   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7461   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7462   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7463   PetscFunctionReturn(PETSC_SUCCESS);
7464 }
7465 
7466 /*@C
7467   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7468 
7469   Collective
7470 
7471   Input Parameter:
7472 . mat - the matrix
7473 
7474   Level: advanced
7475 
7476   Note:
7477   This is not needed, one can just call `MatDestroy()`
7478 
7479 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7480 @*/
7481 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7482 {
7483   PetscFunctionBegin;
7484   PetscAssertPointer(mat, 1);
7485   PetscCall(MatDestroy(mat));
7486   PetscFunctionReturn(PETSC_SUCCESS);
7487 }
7488 
7489 /*@
7490   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7491   replaces the index sets by larger ones that represent submatrices with
7492   additional overlap.
7493 
7494   Collective
7495 
7496   Input Parameters:
7497 + mat - the matrix
7498 . n   - the number of index sets
7499 . is  - the array of index sets (these index sets will changed during the call)
7500 - ov  - the additional overlap requested
7501 
7502   Options Database Key:
7503 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7504 
7505   Level: developer
7506 
7507   Note:
7508   The computed overlap preserves the matrix block sizes when the blocks are square.
7509   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7510   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7511 
7512 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7513 @*/
7514 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7515 {
7516   PetscInt i, bs, cbs;
7517 
7518   PetscFunctionBegin;
7519   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7520   PetscValidType(mat, 1);
7521   PetscValidLogicalCollectiveInt(mat, n, 2);
7522   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7523   if (n) {
7524     PetscAssertPointer(is, 3);
7525     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7526   }
7527   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7528   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7529   MatCheckPreallocated(mat, 1);
7530 
7531   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7532   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7533   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7534   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7535   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7536   if (bs == cbs) {
7537     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7538   }
7539   PetscFunctionReturn(PETSC_SUCCESS);
7540 }
7541 
7542 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7543 
7544 /*@
7545   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7546   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7547   additional overlap.
7548 
7549   Collective
7550 
7551   Input Parameters:
7552 + mat - the matrix
7553 . n   - the number of index sets
7554 . is  - the array of index sets (these index sets will changed during the call)
7555 - ov  - the additional overlap requested
7556 
7557   `   Options Database Key:
7558 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7559 
7560   Level: developer
7561 
7562 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7563 @*/
7564 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7565 {
7566   PetscInt i;
7567 
7568   PetscFunctionBegin;
7569   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7570   PetscValidType(mat, 1);
7571   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7572   if (n) {
7573     PetscAssertPointer(is, 3);
7574     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7575   }
7576   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7577   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7578   MatCheckPreallocated(mat, 1);
7579   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7580   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7581   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7582   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7583   PetscFunctionReturn(PETSC_SUCCESS);
7584 }
7585 
7586 /*@
7587   MatGetBlockSize - Returns the matrix block size.
7588 
7589   Not Collective
7590 
7591   Input Parameter:
7592 . mat - the matrix
7593 
7594   Output Parameter:
7595 . bs - block size
7596 
7597   Level: intermediate
7598 
7599   Notes:
7600   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7601 
7602   If the block size has not been set yet this routine returns 1.
7603 
7604 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7605 @*/
7606 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7607 {
7608   PetscFunctionBegin;
7609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7610   PetscAssertPointer(bs, 2);
7611   *bs = PetscAbs(mat->rmap->bs);
7612   PetscFunctionReturn(PETSC_SUCCESS);
7613 }
7614 
7615 /*@
7616   MatGetBlockSizes - Returns the matrix block row and column sizes.
7617 
7618   Not Collective
7619 
7620   Input Parameter:
7621 . mat - the matrix
7622 
7623   Output Parameters:
7624 + rbs - row block size
7625 - cbs - column block size
7626 
7627   Level: intermediate
7628 
7629   Notes:
7630   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7631   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7632 
7633   If a block size has not been set yet this routine returns 1.
7634 
7635 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7636 @*/
7637 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7638 {
7639   PetscFunctionBegin;
7640   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7641   if (rbs) PetscAssertPointer(rbs, 2);
7642   if (cbs) PetscAssertPointer(cbs, 3);
7643   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7644   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7645   PetscFunctionReturn(PETSC_SUCCESS);
7646 }
7647 
7648 /*@
7649   MatSetBlockSize - Sets the matrix block size.
7650 
7651   Logically Collective
7652 
7653   Input Parameters:
7654 + mat - the matrix
7655 - bs  - block size
7656 
7657   Level: intermediate
7658 
7659   Notes:
7660   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7661   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7662 
7663   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7664   is compatible with the matrix local sizes.
7665 
7666 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7667 @*/
7668 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7669 {
7670   PetscFunctionBegin;
7671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7672   PetscValidLogicalCollectiveInt(mat, bs, 2);
7673   PetscCall(MatSetBlockSizes(mat, bs, bs));
7674   PetscFunctionReturn(PETSC_SUCCESS);
7675 }
7676 
7677 typedef struct {
7678   PetscInt         n;
7679   IS              *is;
7680   Mat             *mat;
7681   PetscObjectState nonzerostate;
7682   Mat              C;
7683 } EnvelopeData;
7684 
7685 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7686 {
7687   EnvelopeData *edata = (EnvelopeData *)*ptr;
7688 
7689   PetscFunctionBegin;
7690   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7691   PetscCall(PetscFree(edata->is));
7692   PetscCall(PetscFree(edata));
7693   PetscFunctionReturn(PETSC_SUCCESS);
7694 }
7695 
7696 /*@
7697   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7698   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7699 
7700   Collective
7701 
7702   Input Parameter:
7703 . mat - the matrix
7704 
7705   Level: intermediate
7706 
7707   Notes:
7708   There can be zeros within the blocks
7709 
7710   The blocks can overlap between processes, including laying on more than two processes
7711 
7712 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7713 @*/
7714 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7715 {
7716   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7717   PetscInt          *diag, *odiag, sc;
7718   VecScatter         scatter;
7719   PetscScalar       *seqv;
7720   const PetscScalar *parv;
7721   const PetscInt    *ia, *ja;
7722   PetscBool          set, flag, done;
7723   Mat                AA = mat, A;
7724   MPI_Comm           comm;
7725   PetscMPIInt        rank, size, tag;
7726   MPI_Status         status;
7727   PetscContainer     container;
7728   EnvelopeData      *edata;
7729   Vec                seq, par;
7730   IS                 isglobal;
7731 
7732   PetscFunctionBegin;
7733   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7734   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7735   if (!set || !flag) {
7736     /* TODO: only needs nonzero structure of transpose */
7737     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7738     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7739   }
7740   PetscCall(MatAIJGetLocalMat(AA, &A));
7741   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7742   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7743 
7744   PetscCall(MatGetLocalSize(mat, &n, NULL));
7745   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7746   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7747   PetscCallMPI(MPI_Comm_size(comm, &size));
7748   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7749 
7750   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7751 
7752   if (rank > 0) {
7753     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7754     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7755   }
7756   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7757   for (i = 0; i < n; i++) {
7758     env = PetscMax(env, ja[ia[i + 1] - 1]);
7759     II  = rstart + i;
7760     if (env == II) {
7761       starts[lblocks]  = tbs;
7762       sizes[lblocks++] = 1 + II - tbs;
7763       tbs              = 1 + II;
7764     }
7765   }
7766   if (rank < size - 1) {
7767     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7768     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7769   }
7770 
7771   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7772   if (!set || !flag) PetscCall(MatDestroy(&AA));
7773   PetscCall(MatDestroy(&A));
7774 
7775   PetscCall(PetscNew(&edata));
7776   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7777   edata->n = lblocks;
7778   /* create IS needed for extracting blocks from the original matrix */
7779   PetscCall(PetscMalloc1(lblocks, &edata->is));
7780   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7781 
7782   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7783   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7784   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7785   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7786   PetscCall(MatSetType(edata->C, MATAIJ));
7787 
7788   /* Communicate the start and end of each row, from each block to the correct rank */
7789   /* TODO: Use PetscSF instead of VecScatter */
7790   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7791   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7792   PetscCall(VecGetArrayWrite(seq, &seqv));
7793   for (PetscInt i = 0; i < lblocks; i++) {
7794     for (PetscInt j = 0; j < sizes[i]; j++) {
7795       seqv[cnt]     = starts[i];
7796       seqv[cnt + 1] = starts[i] + sizes[i];
7797       cnt += 2;
7798     }
7799   }
7800   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7801   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7802   sc -= cnt;
7803   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7804   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7805   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7806   PetscCall(ISDestroy(&isglobal));
7807   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7808   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7809   PetscCall(VecScatterDestroy(&scatter));
7810   PetscCall(VecDestroy(&seq));
7811   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7812   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7813   PetscCall(VecGetArrayRead(par, &parv));
7814   cnt = 0;
7815   PetscCall(MatGetSize(mat, NULL, &n));
7816   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7817     PetscInt start, end, d = 0, od = 0;
7818 
7819     start = (PetscInt)PetscRealPart(parv[cnt]);
7820     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7821     cnt += 2;
7822 
7823     if (start < cstart) {
7824       od += cstart - start + n - cend;
7825       d += cend - cstart;
7826     } else if (start < cend) {
7827       od += n - cend;
7828       d += cend - start;
7829     } else od += n - start;
7830     if (end <= cstart) {
7831       od -= cstart - end + n - cend;
7832       d -= cend - cstart;
7833     } else if (end < cend) {
7834       od -= n - cend;
7835       d -= cend - end;
7836     } else od -= n - end;
7837 
7838     odiag[i] = od;
7839     diag[i]  = d;
7840   }
7841   PetscCall(VecRestoreArrayRead(par, &parv));
7842   PetscCall(VecDestroy(&par));
7843   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7844   PetscCall(PetscFree2(diag, odiag));
7845   PetscCall(PetscFree2(sizes, starts));
7846 
7847   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7848   PetscCall(PetscContainerSetPointer(container, edata));
7849   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7850   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7851   PetscCall(PetscObjectDereference((PetscObject)container));
7852   PetscFunctionReturn(PETSC_SUCCESS);
7853 }
7854 
7855 /*@
7856   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7857 
7858   Collective
7859 
7860   Input Parameters:
7861 + A     - the matrix
7862 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7863 
7864   Output Parameter:
7865 . C - matrix with inverted block diagonal of `A`
7866 
7867   Level: advanced
7868 
7869   Note:
7870   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7871 
7872 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7873 @*/
7874 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7875 {
7876   PetscContainer   container;
7877   EnvelopeData    *edata;
7878   PetscObjectState nonzerostate;
7879 
7880   PetscFunctionBegin;
7881   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7882   if (!container) {
7883     PetscCall(MatComputeVariableBlockEnvelope(A));
7884     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7885   }
7886   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7887   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7888   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7889   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7890 
7891   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7892   *C = edata->C;
7893 
7894   for (PetscInt i = 0; i < edata->n; i++) {
7895     Mat          D;
7896     PetscScalar *dvalues;
7897 
7898     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7899     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7900     PetscCall(MatSeqDenseInvert(D));
7901     PetscCall(MatDenseGetArray(D, &dvalues));
7902     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7903     PetscCall(MatDestroy(&D));
7904   }
7905   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7906   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7907   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7908   PetscFunctionReturn(PETSC_SUCCESS);
7909 }
7910 
7911 /*@
7912   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7913 
7914   Not Collective
7915 
7916   Input Parameters:
7917 + mat     - the matrix
7918 . nblocks - the number of blocks on this process, each block can only exist on a single process
7919 - bsizes  - the block sizes
7920 
7921   Level: intermediate
7922 
7923   Notes:
7924   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7925 
7926   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.
7927 
7928 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7929           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7930 @*/
7931 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7932 {
7933   PetscInt ncnt = 0, nlocal;
7934 
7935   PetscFunctionBegin;
7936   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7937   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7938   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);
7939   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7940   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);
7941   PetscCall(PetscFree(mat->bsizes));
7942   mat->nblocks = nblocks;
7943   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7944   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7945   PetscFunctionReturn(PETSC_SUCCESS);
7946 }
7947 
7948 /*@C
7949   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7950 
7951   Not Collective; No Fortran Support
7952 
7953   Input Parameter:
7954 . mat - the matrix
7955 
7956   Output Parameters:
7957 + nblocks - the number of blocks on this process
7958 - bsizes  - the block sizes
7959 
7960   Level: intermediate
7961 
7962 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7963 @*/
7964 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7965 {
7966   PetscFunctionBegin;
7967   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7968   if (nblocks) *nblocks = mat->nblocks;
7969   if (bsizes) *bsizes = mat->bsizes;
7970   PetscFunctionReturn(PETSC_SUCCESS);
7971 }
7972 
7973 /*@
7974   MatSetBlockSizes - Sets the matrix block row and column sizes.
7975 
7976   Logically Collective
7977 
7978   Input Parameters:
7979 + mat - the matrix
7980 . rbs - row block size
7981 - cbs - column block size
7982 
7983   Level: intermediate
7984 
7985   Notes:
7986   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7987   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7988   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7989 
7990   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7991   are compatible with the matrix local sizes.
7992 
7993   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7994 
7995 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7996 @*/
7997 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7998 {
7999   PetscFunctionBegin;
8000   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8001   PetscValidLogicalCollectiveInt(mat, rbs, 2);
8002   PetscValidLogicalCollectiveInt(mat, cbs, 3);
8003   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
8004   if (mat->rmap->refcnt) {
8005     ISLocalToGlobalMapping l2g  = NULL;
8006     PetscLayout            nmap = NULL;
8007 
8008     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
8009     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
8010     PetscCall(PetscLayoutDestroy(&mat->rmap));
8011     mat->rmap          = nmap;
8012     mat->rmap->mapping = l2g;
8013   }
8014   if (mat->cmap->refcnt) {
8015     ISLocalToGlobalMapping l2g  = NULL;
8016     PetscLayout            nmap = NULL;
8017 
8018     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
8019     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
8020     PetscCall(PetscLayoutDestroy(&mat->cmap));
8021     mat->cmap          = nmap;
8022     mat->cmap->mapping = l2g;
8023   }
8024   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
8025   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
8026   PetscFunctionReturn(PETSC_SUCCESS);
8027 }
8028 
8029 /*@
8030   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
8031 
8032   Logically Collective
8033 
8034   Input Parameters:
8035 + mat     - the matrix
8036 . fromRow - matrix from which to copy row block size
8037 - fromCol - matrix from which to copy column block size (can be same as fromRow)
8038 
8039   Level: developer
8040 
8041 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
8042 @*/
8043 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8044 {
8045   PetscFunctionBegin;
8046   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8047   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8048   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8049   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8050   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8051   PetscFunctionReturn(PETSC_SUCCESS);
8052 }
8053 
8054 /*@
8055   MatResidual - Default routine to calculate the residual r = b - Ax
8056 
8057   Collective
8058 
8059   Input Parameters:
8060 + mat - the matrix
8061 . b   - the right-hand-side
8062 - x   - the approximate solution
8063 
8064   Output Parameter:
8065 . r - location to store the residual
8066 
8067   Level: developer
8068 
8069 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8070 @*/
8071 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8072 {
8073   PetscFunctionBegin;
8074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8075   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8076   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8077   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8078   PetscValidType(mat, 1);
8079   MatCheckPreallocated(mat, 1);
8080   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8081   if (!mat->ops->residual) {
8082     PetscCall(MatMult(mat, x, r));
8083     PetscCall(VecAYPX(r, -1.0, b));
8084   } else {
8085     PetscUseTypeMethod(mat, residual, b, x, r);
8086   }
8087   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8088   PetscFunctionReturn(PETSC_SUCCESS);
8089 }
8090 
8091 /*MC
8092     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8093 
8094     Synopsis:
8095     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8096 
8097     Not Collective
8098 
8099     Input Parameters:
8100 +   A - the matrix
8101 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8102 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8103 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8104                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8105                  always used.
8106 
8107     Output Parameters:
8108 +   n - number of local rows in the (possibly compressed) matrix
8109 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8110 .   ja - the column indices
8111 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8112            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8113 
8114     Level: developer
8115 
8116     Note:
8117     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8118 
8119 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8120 M*/
8121 
8122 /*MC
8123     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8124 
8125     Synopsis:
8126     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8127 
8128     Not Collective
8129 
8130     Input Parameters:
8131 +   A - the  matrix
8132 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8133 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8134     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8135                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8136                  always used.
8137 .   n - number of local rows in the (possibly compressed) matrix
8138 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8139 .   ja - the column indices
8140 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8141            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8142 
8143     Level: developer
8144 
8145 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8146 M*/
8147 
8148 /*@C
8149   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8150 
8151   Collective
8152 
8153   Input Parameters:
8154 + mat             - the matrix
8155 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8156 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8157 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8158                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8159                  always used.
8160 
8161   Output Parameters:
8162 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8163 . 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
8164 . ja   - the column indices, use `NULL` if not needed
8165 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8166            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8167 
8168   Level: developer
8169 
8170   Notes:
8171   You CANNOT change any of the ia[] or ja[] values.
8172 
8173   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8174 
8175   Fortran Notes:
8176   Use
8177 .vb
8178     PetscInt, pointer :: ia(:),ja(:)
8179     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8180     ! Access the ith and jth entries via ia(i) and ja(j)
8181 .ve
8182 
8183   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8184 
8185 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8186 @*/
8187 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8188 {
8189   PetscFunctionBegin;
8190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8191   PetscValidType(mat, 1);
8192   if (n) PetscAssertPointer(n, 5);
8193   if (ia) PetscAssertPointer(ia, 6);
8194   if (ja) PetscAssertPointer(ja, 7);
8195   if (done) PetscAssertPointer(done, 8);
8196   MatCheckPreallocated(mat, 1);
8197   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8198   else {
8199     if (done) *done = PETSC_TRUE;
8200     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8201     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8202     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8203   }
8204   PetscFunctionReturn(PETSC_SUCCESS);
8205 }
8206 
8207 /*@C
8208   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8209 
8210   Collective
8211 
8212   Input Parameters:
8213 + mat             - the matrix
8214 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8215 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8216                 symmetrized
8217 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8218                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8219                  always used.
8220 . n               - number of columns in the (possibly compressed) matrix
8221 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8222 - ja              - the row indices
8223 
8224   Output Parameter:
8225 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8226 
8227   Level: developer
8228 
8229 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8230 @*/
8231 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8232 {
8233   PetscFunctionBegin;
8234   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8235   PetscValidType(mat, 1);
8236   PetscAssertPointer(n, 5);
8237   if (ia) PetscAssertPointer(ia, 6);
8238   if (ja) PetscAssertPointer(ja, 7);
8239   PetscAssertPointer(done, 8);
8240   MatCheckPreallocated(mat, 1);
8241   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8242   else {
8243     *done = PETSC_TRUE;
8244     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8245   }
8246   PetscFunctionReturn(PETSC_SUCCESS);
8247 }
8248 
8249 /*@C
8250   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8251 
8252   Collective
8253 
8254   Input Parameters:
8255 + mat             - the matrix
8256 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8257 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8258 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8259                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8260                     always used.
8261 . n               - size of (possibly compressed) matrix
8262 . ia              - the row pointers
8263 - ja              - the column indices
8264 
8265   Output Parameter:
8266 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8267 
8268   Level: developer
8269 
8270   Note:
8271   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8272   us of the array after it has been restored. If you pass `NULL`, it will
8273   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8274 
8275   Fortran Note:
8276   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8277 
8278 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8279 @*/
8280 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8281 {
8282   PetscFunctionBegin;
8283   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8284   PetscValidType(mat, 1);
8285   if (ia) PetscAssertPointer(ia, 6);
8286   if (ja) PetscAssertPointer(ja, 7);
8287   if (done) PetscAssertPointer(done, 8);
8288   MatCheckPreallocated(mat, 1);
8289 
8290   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8291   else {
8292     if (done) *done = PETSC_TRUE;
8293     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8294     if (n) *n = 0;
8295     if (ia) *ia = NULL;
8296     if (ja) *ja = NULL;
8297   }
8298   PetscFunctionReturn(PETSC_SUCCESS);
8299 }
8300 
8301 /*@C
8302   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8303 
8304   Collective
8305 
8306   Input Parameters:
8307 + mat             - the matrix
8308 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8309 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8310 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8311                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8312                     always used.
8313 
8314   Output Parameters:
8315 + n    - size of (possibly compressed) matrix
8316 . ia   - the column pointers
8317 . ja   - the row indices
8318 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8319 
8320   Level: developer
8321 
8322 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8323 @*/
8324 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8325 {
8326   PetscFunctionBegin;
8327   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8328   PetscValidType(mat, 1);
8329   if (ia) PetscAssertPointer(ia, 6);
8330   if (ja) PetscAssertPointer(ja, 7);
8331   PetscAssertPointer(done, 8);
8332   MatCheckPreallocated(mat, 1);
8333 
8334   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8335   else {
8336     *done = PETSC_TRUE;
8337     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8338     if (n) *n = 0;
8339     if (ia) *ia = NULL;
8340     if (ja) *ja = NULL;
8341   }
8342   PetscFunctionReturn(PETSC_SUCCESS);
8343 }
8344 
8345 /*@
8346   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8347   `MatGetColumnIJ()`.
8348 
8349   Collective
8350 
8351   Input Parameters:
8352 + mat        - the matrix
8353 . ncolors    - maximum color value
8354 . n          - number of entries in colorarray
8355 - colorarray - array indicating color for each column
8356 
8357   Output Parameter:
8358 . iscoloring - coloring generated using colorarray information
8359 
8360   Level: developer
8361 
8362 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8363 @*/
8364 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8365 {
8366   PetscFunctionBegin;
8367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8368   PetscValidType(mat, 1);
8369   PetscAssertPointer(colorarray, 4);
8370   PetscAssertPointer(iscoloring, 5);
8371   MatCheckPreallocated(mat, 1);
8372 
8373   if (!mat->ops->coloringpatch) {
8374     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8375   } else {
8376     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8377   }
8378   PetscFunctionReturn(PETSC_SUCCESS);
8379 }
8380 
8381 /*@
8382   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8383 
8384   Logically Collective
8385 
8386   Input Parameter:
8387 . mat - the factored matrix to be reset
8388 
8389   Level: developer
8390 
8391   Notes:
8392   This routine should be used only with factored matrices formed by in-place
8393   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8394   format).  This option can save memory, for example, when solving nonlinear
8395   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8396   ILU(0) preconditioner.
8397 
8398   One can specify in-place ILU(0) factorization by calling
8399 .vb
8400      PCType(pc,PCILU);
8401      PCFactorSeUseInPlace(pc);
8402 .ve
8403   or by using the options -pc_type ilu -pc_factor_in_place
8404 
8405   In-place factorization ILU(0) can also be used as a local
8406   solver for the blocks within the block Jacobi or additive Schwarz
8407   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8408   for details on setting local solver options.
8409 
8410   Most users should employ the `KSP` interface for linear solvers
8411   instead of working directly with matrix algebra routines such as this.
8412   See, e.g., `KSPCreate()`.
8413 
8414 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8415 @*/
8416 PetscErrorCode MatSetUnfactored(Mat mat)
8417 {
8418   PetscFunctionBegin;
8419   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8420   PetscValidType(mat, 1);
8421   MatCheckPreallocated(mat, 1);
8422   mat->factortype = MAT_FACTOR_NONE;
8423   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8424   PetscUseTypeMethod(mat, setunfactored);
8425   PetscFunctionReturn(PETSC_SUCCESS);
8426 }
8427 
8428 /*MC
8429     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8430 
8431     Synopsis:
8432     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8433 
8434     Not Collective
8435 
8436     Input Parameter:
8437 .   x - matrix
8438 
8439     Output Parameters:
8440 +   xx_v - the Fortran pointer to the array
8441 -   ierr - error code
8442 
8443     Example of Usage:
8444 .vb
8445       PetscScalar, pointer xx_v(:,:)
8446       ....
8447       call MatDenseGetArrayF90(x,xx_v,ierr)
8448       a = xx_v(3)
8449       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8450 .ve
8451 
8452     Level: advanced
8453 
8454 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8455 M*/
8456 
8457 /*MC
8458     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8459     accessed with `MatDenseGetArrayF90()`.
8460 
8461     Synopsis:
8462     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8463 
8464     Not Collective
8465 
8466     Input Parameters:
8467 +   x - matrix
8468 -   xx_v - the Fortran90 pointer to the array
8469 
8470     Output Parameter:
8471 .   ierr - error code
8472 
8473     Example of Usage:
8474 .vb
8475        PetscScalar, pointer xx_v(:,:)
8476        ....
8477        call MatDenseGetArrayF90(x,xx_v,ierr)
8478        a = xx_v(3)
8479        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8480 .ve
8481 
8482     Level: advanced
8483 
8484 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8485 M*/
8486 
8487 /*MC
8488     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8489 
8490     Synopsis:
8491     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8492 
8493     Not Collective
8494 
8495     Input Parameter:
8496 .   x - matrix
8497 
8498     Output Parameters:
8499 +   xx_v - the Fortran pointer to the array
8500 -   ierr - error code
8501 
8502     Example of Usage:
8503 .vb
8504       PetscScalar, pointer xx_v(:)
8505       ....
8506       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8507       a = xx_v(3)
8508       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8509 .ve
8510 
8511     Level: advanced
8512 
8513 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8514 M*/
8515 
8516 /*MC
8517     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8518     accessed with `MatSeqAIJGetArrayF90()`.
8519 
8520     Synopsis:
8521     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8522 
8523     Not Collective
8524 
8525     Input Parameters:
8526 +   x - matrix
8527 -   xx_v - the Fortran90 pointer to the array
8528 
8529     Output Parameter:
8530 .   ierr - error code
8531 
8532     Example of Usage:
8533 .vb
8534        PetscScalar, pointer xx_v(:)
8535        ....
8536        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8537        a = xx_v(3)
8538        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8539 .ve
8540 
8541     Level: advanced
8542 
8543 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8544 M*/
8545 
8546 /*@
8547   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8548   as the original matrix.
8549 
8550   Collective
8551 
8552   Input Parameters:
8553 + mat   - the original matrix
8554 . isrow - parallel `IS` containing the rows this processor should obtain
8555 . 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.
8556 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8557 
8558   Output Parameter:
8559 . newmat - the new submatrix, of the same type as the original matrix
8560 
8561   Level: advanced
8562 
8563   Notes:
8564   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8565 
8566   Some matrix types place restrictions on the row and column indices, such
8567   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;
8568   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8569 
8570   The index sets may not have duplicate entries.
8571 
8572   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8573   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8574   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8575   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8576   you are finished using it.
8577 
8578   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8579   the input matrix.
8580 
8581   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8582 
8583   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8584   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8585 
8586   Example usage:
8587   Consider the following 8x8 matrix with 34 non-zero values, that is
8588   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8589   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8590   as follows
8591 .vb
8592             1  2  0  |  0  3  0  |  0  4
8593     Proc0   0  5  6  |  7  0  0  |  8  0
8594             9  0 10  | 11  0  0  | 12  0
8595     -------------------------------------
8596            13  0 14  | 15 16 17  |  0  0
8597     Proc1   0 18  0  | 19 20 21  |  0  0
8598             0  0  0  | 22 23  0  | 24  0
8599     -------------------------------------
8600     Proc2  25 26 27  |  0  0 28  | 29  0
8601            30  0  0  | 31 32 33  |  0 34
8602 .ve
8603 
8604   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8605 
8606 .vb
8607             2  0  |  0  3  0  |  0
8608     Proc0   5  6  |  7  0  0  |  8
8609     -------------------------------
8610     Proc1  18  0  | 19 20 21  |  0
8611     -------------------------------
8612     Proc2  26 27  |  0  0 28  | 29
8613             0  0  | 31 32 33  |  0
8614 .ve
8615 
8616 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8617 @*/
8618 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8619 {
8620   PetscMPIInt size;
8621   Mat        *local;
8622   IS          iscoltmp;
8623   PetscBool   flg;
8624 
8625   PetscFunctionBegin;
8626   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8627   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8628   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8629   PetscAssertPointer(newmat, 5);
8630   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8631   PetscValidType(mat, 1);
8632   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8633   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8634 
8635   MatCheckPreallocated(mat, 1);
8636   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8637 
8638   if (!iscol || isrow == iscol) {
8639     PetscBool   stride;
8640     PetscMPIInt grabentirematrix = 0, grab;
8641     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8642     if (stride) {
8643       PetscInt first, step, n, rstart, rend;
8644       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8645       if (step == 1) {
8646         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8647         if (rstart == first) {
8648           PetscCall(ISGetLocalSize(isrow, &n));
8649           if (n == rend - rstart) grabentirematrix = 1;
8650         }
8651       }
8652     }
8653     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8654     if (grab) {
8655       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8656       if (cll == MAT_INITIAL_MATRIX) {
8657         *newmat = mat;
8658         PetscCall(PetscObjectReference((PetscObject)mat));
8659       }
8660       PetscFunctionReturn(PETSC_SUCCESS);
8661     }
8662   }
8663 
8664   if (!iscol) {
8665     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8666   } else {
8667     iscoltmp = iscol;
8668   }
8669 
8670   /* if original matrix is on just one processor then use submatrix generated */
8671   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8672     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8673     goto setproperties;
8674   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8675     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8676     *newmat = *local;
8677     PetscCall(PetscFree(local));
8678     goto setproperties;
8679   } else if (!mat->ops->createsubmatrix) {
8680     /* Create a new matrix type that implements the operation using the full matrix */
8681     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8682     switch (cll) {
8683     case MAT_INITIAL_MATRIX:
8684       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8685       break;
8686     case MAT_REUSE_MATRIX:
8687       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8688       break;
8689     default:
8690       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8691     }
8692     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8693     goto setproperties;
8694   }
8695 
8696   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8697   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8698   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8699 
8700 setproperties:
8701   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8702     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8703     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8704   }
8705   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8706   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8707   PetscFunctionReturn(PETSC_SUCCESS);
8708 }
8709 
8710 /*@
8711   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8712 
8713   Not Collective
8714 
8715   Input Parameters:
8716 + A - the matrix we wish to propagate options from
8717 - B - the matrix we wish to propagate options to
8718 
8719   Level: beginner
8720 
8721   Note:
8722   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8723 
8724 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8725 @*/
8726 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8727 {
8728   PetscFunctionBegin;
8729   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8730   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8731   B->symmetry_eternal            = A->symmetry_eternal;
8732   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8733   B->symmetric                   = A->symmetric;
8734   B->structurally_symmetric      = A->structurally_symmetric;
8735   B->spd                         = A->spd;
8736   B->hermitian                   = A->hermitian;
8737   PetscFunctionReturn(PETSC_SUCCESS);
8738 }
8739 
8740 /*@
8741   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8742   used during the assembly process to store values that belong to
8743   other processors.
8744 
8745   Not Collective
8746 
8747   Input Parameters:
8748 + mat   - the matrix
8749 . size  - the initial size of the stash.
8750 - bsize - the initial size of the block-stash(if used).
8751 
8752   Options Database Keys:
8753 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8754 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8755 
8756   Level: intermediate
8757 
8758   Notes:
8759   The block-stash is used for values set with `MatSetValuesBlocked()` while
8760   the stash is used for values set with `MatSetValues()`
8761 
8762   Run with the option -info and look for output of the form
8763   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8764   to determine the appropriate value, MM, to use for size and
8765   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8766   to determine the value, BMM to use for bsize
8767 
8768 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8769 @*/
8770 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8771 {
8772   PetscFunctionBegin;
8773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8774   PetscValidType(mat, 1);
8775   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8776   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8777   PetscFunctionReturn(PETSC_SUCCESS);
8778 }
8779 
8780 /*@
8781   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8782   the matrix
8783 
8784   Neighbor-wise Collective
8785 
8786   Input Parameters:
8787 + A - the matrix
8788 . x - the vector to be multiplied by the interpolation operator
8789 - y - the vector to be added to the result
8790 
8791   Output Parameter:
8792 . w - the resulting vector
8793 
8794   Level: intermediate
8795 
8796   Notes:
8797   `w` may be the same vector as `y`.
8798 
8799   This allows one to use either the restriction or interpolation (its transpose)
8800   matrix to do the interpolation
8801 
8802 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8803 @*/
8804 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8805 {
8806   PetscInt M, N, Ny;
8807 
8808   PetscFunctionBegin;
8809   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8810   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8811   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8812   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8813   PetscCall(MatGetSize(A, &M, &N));
8814   PetscCall(VecGetSize(y, &Ny));
8815   if (M == Ny) {
8816     PetscCall(MatMultAdd(A, x, y, w));
8817   } else {
8818     PetscCall(MatMultTransposeAdd(A, x, y, w));
8819   }
8820   PetscFunctionReturn(PETSC_SUCCESS);
8821 }
8822 
8823 /*@
8824   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8825   the matrix
8826 
8827   Neighbor-wise Collective
8828 
8829   Input Parameters:
8830 + A - the matrix
8831 - x - the vector to be interpolated
8832 
8833   Output Parameter:
8834 . y - the resulting vector
8835 
8836   Level: intermediate
8837 
8838   Note:
8839   This allows one to use either the restriction or interpolation (its transpose)
8840   matrix to do the interpolation
8841 
8842 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8843 @*/
8844 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8845 {
8846   PetscInt M, N, Ny;
8847 
8848   PetscFunctionBegin;
8849   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8850   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8851   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8852   PetscCall(MatGetSize(A, &M, &N));
8853   PetscCall(VecGetSize(y, &Ny));
8854   if (M == Ny) {
8855     PetscCall(MatMult(A, x, y));
8856   } else {
8857     PetscCall(MatMultTranspose(A, x, y));
8858   }
8859   PetscFunctionReturn(PETSC_SUCCESS);
8860 }
8861 
8862 /*@
8863   MatRestrict - $y = A*x$ or $A^T*x$
8864 
8865   Neighbor-wise Collective
8866 
8867   Input Parameters:
8868 + A - the matrix
8869 - x - the vector to be restricted
8870 
8871   Output Parameter:
8872 . y - the resulting vector
8873 
8874   Level: intermediate
8875 
8876   Note:
8877   This allows one to use either the restriction or interpolation (its transpose)
8878   matrix to do the restriction
8879 
8880 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8881 @*/
8882 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8883 {
8884   PetscInt M, N, Nx;
8885 
8886   PetscFunctionBegin;
8887   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8888   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8889   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8890   PetscCall(MatGetSize(A, &M, &N));
8891   PetscCall(VecGetSize(x, &Nx));
8892   if (M == Nx) {
8893     PetscCall(MatMultTranspose(A, x, y));
8894   } else {
8895     PetscCall(MatMult(A, x, y));
8896   }
8897   PetscFunctionReturn(PETSC_SUCCESS);
8898 }
8899 
8900 /*@
8901   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8902 
8903   Neighbor-wise Collective
8904 
8905   Input Parameters:
8906 + A - the matrix
8907 . x - the input dense matrix to be multiplied
8908 - w - the input dense matrix to be added to the result
8909 
8910   Output Parameter:
8911 . y - the output dense matrix
8912 
8913   Level: intermediate
8914 
8915   Note:
8916   This allows one to use either the restriction or interpolation (its transpose)
8917   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8918   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8919 
8920 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8921 @*/
8922 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8923 {
8924   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8925   PetscBool trans = PETSC_TRUE;
8926   MatReuse  reuse = MAT_INITIAL_MATRIX;
8927 
8928   PetscFunctionBegin;
8929   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8930   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8931   PetscValidType(x, 2);
8932   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8933   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8934   PetscCall(MatGetSize(A, &M, &N));
8935   PetscCall(MatGetSize(x, &Mx, &Nx));
8936   if (N == Mx) trans = PETSC_FALSE;
8937   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);
8938   Mo = trans ? N : M;
8939   if (*y) {
8940     PetscCall(MatGetSize(*y, &My, &Ny));
8941     if (Mo == My && Nx == Ny) {
8942       reuse = MAT_REUSE_MATRIX;
8943     } else {
8944       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);
8945       PetscCall(MatDestroy(y));
8946     }
8947   }
8948 
8949   if (w && *y == w) { /* this is to minimize changes in PCMG */
8950     PetscBool flg;
8951 
8952     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8953     if (w) {
8954       PetscInt My, Ny, Mw, Nw;
8955 
8956       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8957       PetscCall(MatGetSize(*y, &My, &Ny));
8958       PetscCall(MatGetSize(w, &Mw, &Nw));
8959       if (!flg || My != Mw || Ny != Nw) w = NULL;
8960     }
8961     if (!w) {
8962       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8963       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8964       PetscCall(PetscObjectDereference((PetscObject)w));
8965     } else {
8966       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8967     }
8968   }
8969   if (!trans) {
8970     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8971   } else {
8972     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8973   }
8974   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8975   PetscFunctionReturn(PETSC_SUCCESS);
8976 }
8977 
8978 /*@
8979   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8980 
8981   Neighbor-wise Collective
8982 
8983   Input Parameters:
8984 + A - the matrix
8985 - x - the input dense matrix
8986 
8987   Output Parameter:
8988 . y - the output dense matrix
8989 
8990   Level: intermediate
8991 
8992   Note:
8993   This allows one to use either the restriction or interpolation (its transpose)
8994   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8995   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8996 
8997 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8998 @*/
8999 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
9000 {
9001   PetscFunctionBegin;
9002   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
9003   PetscFunctionReturn(PETSC_SUCCESS);
9004 }
9005 
9006 /*@
9007   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
9008 
9009   Neighbor-wise Collective
9010 
9011   Input Parameters:
9012 + A - the matrix
9013 - x - the input dense matrix
9014 
9015   Output Parameter:
9016 . y - the output dense matrix
9017 
9018   Level: intermediate
9019 
9020   Note:
9021   This allows one to use either the restriction or interpolation (its transpose)
9022   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
9023   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
9024 
9025 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
9026 @*/
9027 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
9028 {
9029   PetscFunctionBegin;
9030   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
9031   PetscFunctionReturn(PETSC_SUCCESS);
9032 }
9033 
9034 /*@
9035   MatGetNullSpace - retrieves the null space of a matrix.
9036 
9037   Logically Collective
9038 
9039   Input Parameters:
9040 + mat    - the matrix
9041 - nullsp - the null space object
9042 
9043   Level: developer
9044 
9045 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
9046 @*/
9047 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
9048 {
9049   PetscFunctionBegin;
9050   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9051   PetscAssertPointer(nullsp, 2);
9052   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
9053   PetscFunctionReturn(PETSC_SUCCESS);
9054 }
9055 
9056 /*@C
9057   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
9058 
9059   Logically Collective
9060 
9061   Input Parameters:
9062 + n   - the number of matrices
9063 - mat - the array of matrices
9064 
9065   Output Parameters:
9066 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
9067 
9068   Level: developer
9069 
9070   Note:
9071   Call `MatRestoreNullspaces()` to provide these to another array of matrices
9072 
9073 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9074           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
9075 @*/
9076 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9077 {
9078   PetscFunctionBegin;
9079   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9080   PetscAssertPointer(mat, 2);
9081   PetscAssertPointer(nullsp, 3);
9082 
9083   PetscCall(PetscCalloc1(3 * n, nullsp));
9084   for (PetscInt i = 0; i < n; i++) {
9085     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9086     (*nullsp)[i] = mat[i]->nullsp;
9087     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9088     (*nullsp)[n + i] = mat[i]->nearnullsp;
9089     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9090     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9091     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9092   }
9093   PetscFunctionReturn(PETSC_SUCCESS);
9094 }
9095 
9096 /*@C
9097   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9098 
9099   Logically Collective
9100 
9101   Input Parameters:
9102 + n      - the number of matrices
9103 . mat    - the array of matrices
9104 - nullsp - an array of null spaces
9105 
9106   Level: developer
9107 
9108   Note:
9109   Call `MatGetNullSpaces()` to create `nullsp`
9110 
9111 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9112           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9113 @*/
9114 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9115 {
9116   PetscFunctionBegin;
9117   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9118   PetscAssertPointer(mat, 2);
9119   PetscAssertPointer(nullsp, 3);
9120   PetscAssertPointer(*nullsp, 3);
9121 
9122   for (PetscInt i = 0; i < n; i++) {
9123     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9124     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9125     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9126     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9127     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9128     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9129     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9130   }
9131   PetscCall(PetscFree(*nullsp));
9132   PetscFunctionReturn(PETSC_SUCCESS);
9133 }
9134 
9135 /*@
9136   MatSetNullSpace - attaches a null space to a matrix.
9137 
9138   Logically Collective
9139 
9140   Input Parameters:
9141 + mat    - the matrix
9142 - nullsp - the null space object
9143 
9144   Level: advanced
9145 
9146   Notes:
9147   This null space is used by the `KSP` linear solvers to solve singular systems.
9148 
9149   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`
9150 
9151   For inconsistent singular systems (linear systems where the right-hand side is not in the range of the operator) the `KSP` residuals will not converge to
9152   to zero but the linear system will still be solved in a least squares sense.
9153 
9154   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9155   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)$.
9156   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
9157   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
9158   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$).
9159   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9160 
9161   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9162   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9163   routine also automatically calls `MatSetTransposeNullSpace()`.
9164 
9165   The user should call `MatNullSpaceDestroy()`.
9166 
9167 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9168           `KSPSetPCSide()`
9169 @*/
9170 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9171 {
9172   PetscFunctionBegin;
9173   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9174   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9175   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9176   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9177   mat->nullsp = nullsp;
9178   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9179   PetscFunctionReturn(PETSC_SUCCESS);
9180 }
9181 
9182 /*@
9183   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9184 
9185   Logically Collective
9186 
9187   Input Parameters:
9188 + mat    - the matrix
9189 - nullsp - the null space object
9190 
9191   Level: developer
9192 
9193 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9194 @*/
9195 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9196 {
9197   PetscFunctionBegin;
9198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9199   PetscValidType(mat, 1);
9200   PetscAssertPointer(nullsp, 2);
9201   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9202   PetscFunctionReturn(PETSC_SUCCESS);
9203 }
9204 
9205 /*@
9206   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9207 
9208   Logically Collective
9209 
9210   Input Parameters:
9211 + mat    - the matrix
9212 - nullsp - the null space object
9213 
9214   Level: advanced
9215 
9216   Notes:
9217   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9218 
9219   See `MatSetNullSpace()`
9220 
9221 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9222 @*/
9223 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9224 {
9225   PetscFunctionBegin;
9226   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9227   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9228   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9229   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9230   mat->transnullsp = nullsp;
9231   PetscFunctionReturn(PETSC_SUCCESS);
9232 }
9233 
9234 /*@
9235   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9236   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9237 
9238   Logically Collective
9239 
9240   Input Parameters:
9241 + mat    - the matrix
9242 - nullsp - the null space object
9243 
9244   Level: advanced
9245 
9246   Notes:
9247   Overwrites any previous near null space that may have been attached
9248 
9249   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9250 
9251 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9252 @*/
9253 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9254 {
9255   PetscFunctionBegin;
9256   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9257   PetscValidType(mat, 1);
9258   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9259   MatCheckPreallocated(mat, 1);
9260   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9261   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9262   mat->nearnullsp = nullsp;
9263   PetscFunctionReturn(PETSC_SUCCESS);
9264 }
9265 
9266 /*@
9267   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9268 
9269   Not Collective
9270 
9271   Input Parameter:
9272 . mat - the matrix
9273 
9274   Output Parameter:
9275 . nullsp - the null space object, `NULL` if not set
9276 
9277   Level: advanced
9278 
9279 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9280 @*/
9281 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9282 {
9283   PetscFunctionBegin;
9284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9285   PetscValidType(mat, 1);
9286   PetscAssertPointer(nullsp, 2);
9287   MatCheckPreallocated(mat, 1);
9288   *nullsp = mat->nearnullsp;
9289   PetscFunctionReturn(PETSC_SUCCESS);
9290 }
9291 
9292 /*@
9293   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9294 
9295   Collective
9296 
9297   Input Parameters:
9298 + mat  - the matrix
9299 . row  - row/column permutation
9300 - info - information on desired factorization process
9301 
9302   Level: developer
9303 
9304   Notes:
9305   Probably really in-place only when level of fill is zero, otherwise allocates
9306   new space to store factored matrix and deletes previous memory.
9307 
9308   Most users should employ the `KSP` interface for linear solvers
9309   instead of working directly with matrix algebra routines such as this.
9310   See, e.g., `KSPCreate()`.
9311 
9312   Developer Note:
9313   The Fortran interface is not autogenerated as the
9314   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9315 
9316 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9317 @*/
9318 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9319 {
9320   PetscFunctionBegin;
9321   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9322   PetscValidType(mat, 1);
9323   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9324   PetscAssertPointer(info, 3);
9325   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9326   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9327   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9328   MatCheckPreallocated(mat, 1);
9329   PetscUseTypeMethod(mat, iccfactor, row, info);
9330   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9331   PetscFunctionReturn(PETSC_SUCCESS);
9332 }
9333 
9334 /*@
9335   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9336   ghosted ones.
9337 
9338   Not Collective
9339 
9340   Input Parameters:
9341 + mat  - the matrix
9342 - diag - the diagonal values, including ghost ones
9343 
9344   Level: developer
9345 
9346   Notes:
9347   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9348 
9349   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9350 
9351 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9352 @*/
9353 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9354 {
9355   PetscMPIInt size;
9356 
9357   PetscFunctionBegin;
9358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9359   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9360   PetscValidType(mat, 1);
9361 
9362   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9363   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9364   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9365   if (size == 1) {
9366     PetscInt n, m;
9367     PetscCall(VecGetSize(diag, &n));
9368     PetscCall(MatGetSize(mat, NULL, &m));
9369     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9370     PetscCall(MatDiagonalScale(mat, NULL, diag));
9371   } else {
9372     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9373   }
9374   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9375   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9376   PetscFunctionReturn(PETSC_SUCCESS);
9377 }
9378 
9379 /*@
9380   MatGetInertia - Gets the inertia from a factored matrix
9381 
9382   Collective
9383 
9384   Input Parameter:
9385 . mat - the matrix
9386 
9387   Output Parameters:
9388 + nneg  - number of negative eigenvalues
9389 . nzero - number of zero eigenvalues
9390 - npos  - number of positive eigenvalues
9391 
9392   Level: advanced
9393 
9394   Note:
9395   Matrix must have been factored by `MatCholeskyFactor()`
9396 
9397 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9398 @*/
9399 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9400 {
9401   PetscFunctionBegin;
9402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9403   PetscValidType(mat, 1);
9404   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9405   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9406   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9407   PetscFunctionReturn(PETSC_SUCCESS);
9408 }
9409 
9410 /*@C
9411   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9412 
9413   Neighbor-wise Collective
9414 
9415   Input Parameters:
9416 + mat - the factored matrix obtained with `MatGetFactor()`
9417 - b   - the right-hand-side vectors
9418 
9419   Output Parameter:
9420 . x - the result vectors
9421 
9422   Level: developer
9423 
9424   Note:
9425   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9426   call `MatSolves`(A,x,x).
9427 
9428 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9429 @*/
9430 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9431 {
9432   PetscFunctionBegin;
9433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9434   PetscValidType(mat, 1);
9435   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9436   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9437   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9438 
9439   MatCheckPreallocated(mat, 1);
9440   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9441   PetscUseTypeMethod(mat, solves, b, x);
9442   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9443   PetscFunctionReturn(PETSC_SUCCESS);
9444 }
9445 
9446 /*@
9447   MatIsSymmetric - Test whether a matrix is symmetric
9448 
9449   Collective
9450 
9451   Input Parameters:
9452 + A   - the matrix to test
9453 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9454 
9455   Output Parameter:
9456 . flg - the result
9457 
9458   Level: intermediate
9459 
9460   Notes:
9461   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9462 
9463   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9464 
9465   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9466   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9467 
9468 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9469           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9470 @*/
9471 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9472 {
9473   PetscFunctionBegin;
9474   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9475   PetscAssertPointer(flg, 3);
9476   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9477   else {
9478     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9479     else PetscCall(MatIsTranspose(A, A, tol, flg));
9480     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9481   }
9482   PetscFunctionReturn(PETSC_SUCCESS);
9483 }
9484 
9485 /*@
9486   MatIsHermitian - Test whether a matrix is Hermitian
9487 
9488   Collective
9489 
9490   Input Parameters:
9491 + A   - the matrix to test
9492 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9493 
9494   Output Parameter:
9495 . flg - the result
9496 
9497   Level: intermediate
9498 
9499   Notes:
9500   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9501 
9502   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9503 
9504   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9505   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9506 
9507 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9508           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9509 @*/
9510 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9511 {
9512   PetscFunctionBegin;
9513   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9514   PetscAssertPointer(flg, 3);
9515   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9516   else {
9517     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9518     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9519     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9520   }
9521   PetscFunctionReturn(PETSC_SUCCESS);
9522 }
9523 
9524 /*@
9525   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9526 
9527   Not Collective
9528 
9529   Input Parameter:
9530 . A - the matrix to check
9531 
9532   Output Parameters:
9533 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9534 - flg - the result (only valid if set is `PETSC_TRUE`)
9535 
9536   Level: advanced
9537 
9538   Notes:
9539   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9540   if you want it explicitly checked
9541 
9542   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9543   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9544 
9545 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9546 @*/
9547 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9548 {
9549   PetscFunctionBegin;
9550   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9551   PetscAssertPointer(set, 2);
9552   PetscAssertPointer(flg, 3);
9553   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9554     *set = PETSC_TRUE;
9555     *flg = PetscBool3ToBool(A->symmetric);
9556   } else {
9557     *set = PETSC_FALSE;
9558   }
9559   PetscFunctionReturn(PETSC_SUCCESS);
9560 }
9561 
9562 /*@
9563   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9564 
9565   Not Collective
9566 
9567   Input Parameter:
9568 . A - the matrix to check
9569 
9570   Output Parameters:
9571 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9572 - flg - the result (only valid if set is `PETSC_TRUE`)
9573 
9574   Level: advanced
9575 
9576   Notes:
9577   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9578 
9579   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9580   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9581 
9582 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9583 @*/
9584 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9585 {
9586   PetscFunctionBegin;
9587   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9588   PetscAssertPointer(set, 2);
9589   PetscAssertPointer(flg, 3);
9590   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9591     *set = PETSC_TRUE;
9592     *flg = PetscBool3ToBool(A->spd);
9593   } else {
9594     *set = PETSC_FALSE;
9595   }
9596   PetscFunctionReturn(PETSC_SUCCESS);
9597 }
9598 
9599 /*@
9600   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9601 
9602   Not Collective
9603 
9604   Input Parameter:
9605 . A - the matrix to check
9606 
9607   Output Parameters:
9608 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9609 - flg - the result (only valid if set is `PETSC_TRUE`)
9610 
9611   Level: advanced
9612 
9613   Notes:
9614   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9615   if you want it explicitly checked
9616 
9617   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9618   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9619 
9620 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9621 @*/
9622 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9623 {
9624   PetscFunctionBegin;
9625   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9626   PetscAssertPointer(set, 2);
9627   PetscAssertPointer(flg, 3);
9628   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9629     *set = PETSC_TRUE;
9630     *flg = PetscBool3ToBool(A->hermitian);
9631   } else {
9632     *set = PETSC_FALSE;
9633   }
9634   PetscFunctionReturn(PETSC_SUCCESS);
9635 }
9636 
9637 /*@
9638   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9639 
9640   Collective
9641 
9642   Input Parameter:
9643 . A - the matrix to test
9644 
9645   Output Parameter:
9646 . flg - the result
9647 
9648   Level: intermediate
9649 
9650   Notes:
9651   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9652 
9653   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
9654   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9655 
9656 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9657 @*/
9658 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9659 {
9660   PetscFunctionBegin;
9661   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9662   PetscAssertPointer(flg, 2);
9663   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9664     *flg = PetscBool3ToBool(A->structurally_symmetric);
9665   } else {
9666     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9667     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9668   }
9669   PetscFunctionReturn(PETSC_SUCCESS);
9670 }
9671 
9672 /*@
9673   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9674 
9675   Not Collective
9676 
9677   Input Parameter:
9678 . A - the matrix to check
9679 
9680   Output Parameters:
9681 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9682 - flg - the result (only valid if set is PETSC_TRUE)
9683 
9684   Level: advanced
9685 
9686   Notes:
9687   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
9688   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9689 
9690   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9691 
9692 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9693 @*/
9694 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9695 {
9696   PetscFunctionBegin;
9697   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9698   PetscAssertPointer(set, 2);
9699   PetscAssertPointer(flg, 3);
9700   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9701     *set = PETSC_TRUE;
9702     *flg = PetscBool3ToBool(A->structurally_symmetric);
9703   } else {
9704     *set = PETSC_FALSE;
9705   }
9706   PetscFunctionReturn(PETSC_SUCCESS);
9707 }
9708 
9709 /*@
9710   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9711   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9712 
9713   Not Collective
9714 
9715   Input Parameter:
9716 . mat - the matrix
9717 
9718   Output Parameters:
9719 + nstash    - the size of the stash
9720 . reallocs  - the number of additional mallocs incurred.
9721 . bnstash   - the size of the block stash
9722 - breallocs - the number of additional mallocs incurred.in the block stash
9723 
9724   Level: advanced
9725 
9726 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9727 @*/
9728 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9729 {
9730   PetscFunctionBegin;
9731   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9732   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9733   PetscFunctionReturn(PETSC_SUCCESS);
9734 }
9735 
9736 /*@
9737   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9738   parallel layout, `PetscLayout` for rows and columns
9739 
9740   Collective
9741 
9742   Input Parameter:
9743 . mat - the matrix
9744 
9745   Output Parameters:
9746 + right - (optional) vector that the matrix can be multiplied against
9747 - left  - (optional) vector that the matrix vector product can be stored in
9748 
9749   Level: advanced
9750 
9751   Notes:
9752   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()`.
9753 
9754   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9755 
9756 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9757 @*/
9758 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9759 {
9760   PetscFunctionBegin;
9761   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9762   PetscValidType(mat, 1);
9763   if (mat->ops->getvecs) {
9764     PetscUseTypeMethod(mat, getvecs, right, left);
9765   } else {
9766     if (right) {
9767       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9768       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9769       PetscCall(VecSetType(*right, mat->defaultvectype));
9770 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9771       if (mat->boundtocpu && mat->bindingpropagates) {
9772         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9773         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9774       }
9775 #endif
9776     }
9777     if (left) {
9778       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9779       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9780       PetscCall(VecSetType(*left, mat->defaultvectype));
9781 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9782       if (mat->boundtocpu && mat->bindingpropagates) {
9783         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9784         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9785       }
9786 #endif
9787     }
9788   }
9789   PetscFunctionReturn(PETSC_SUCCESS);
9790 }
9791 
9792 /*@
9793   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9794   with default values.
9795 
9796   Not Collective
9797 
9798   Input Parameter:
9799 . info - the `MatFactorInfo` data structure
9800 
9801   Level: developer
9802 
9803   Notes:
9804   The solvers are generally used through the `KSP` and `PC` objects, for example
9805   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9806 
9807   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9808 
9809 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9810 @*/
9811 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9812 {
9813   PetscFunctionBegin;
9814   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9815   PetscFunctionReturn(PETSC_SUCCESS);
9816 }
9817 
9818 /*@
9819   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9820 
9821   Collective
9822 
9823   Input Parameters:
9824 + mat - the factored matrix
9825 - is  - the index set defining the Schur indices (0-based)
9826 
9827   Level: advanced
9828 
9829   Notes:
9830   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9831 
9832   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9833 
9834   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9835 
9836 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9837           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9838 @*/
9839 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9840 {
9841   PetscErrorCode (*f)(Mat, IS);
9842 
9843   PetscFunctionBegin;
9844   PetscValidType(mat, 1);
9845   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9846   PetscValidType(is, 2);
9847   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9848   PetscCheckSameComm(mat, 1, is, 2);
9849   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9850   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9851   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9852   PetscCall(MatDestroy(&mat->schur));
9853   PetscCall((*f)(mat, is));
9854   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9855   PetscFunctionReturn(PETSC_SUCCESS);
9856 }
9857 
9858 /*@
9859   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9860 
9861   Logically Collective
9862 
9863   Input Parameters:
9864 + F      - the factored matrix obtained by calling `MatGetFactor()`
9865 . S      - location where to return the Schur complement, can be `NULL`
9866 - status - the status of the Schur complement matrix, can be `NULL`
9867 
9868   Level: advanced
9869 
9870   Notes:
9871   You must call `MatFactorSetSchurIS()` before calling this routine.
9872 
9873   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9874 
9875   The routine provides a copy of the Schur matrix stored within the solver data structures.
9876   The caller must destroy the object when it is no longer needed.
9877   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9878 
9879   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)
9880 
9881   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9882 
9883   Developer Note:
9884   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9885   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9886 
9887 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9888 @*/
9889 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9890 {
9891   PetscFunctionBegin;
9892   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9893   if (S) PetscAssertPointer(S, 2);
9894   if (status) PetscAssertPointer(status, 3);
9895   if (S) {
9896     PetscErrorCode (*f)(Mat, Mat *);
9897 
9898     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9899     if (f) {
9900       PetscCall((*f)(F, S));
9901     } else {
9902       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9903     }
9904   }
9905   if (status) *status = F->schur_status;
9906   PetscFunctionReturn(PETSC_SUCCESS);
9907 }
9908 
9909 /*@
9910   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9911 
9912   Logically Collective
9913 
9914   Input Parameters:
9915 + F      - the factored matrix obtained by calling `MatGetFactor()`
9916 . S      - location where to return the Schur complement, can be `NULL`
9917 - status - the status of the Schur complement matrix, can be `NULL`
9918 
9919   Level: advanced
9920 
9921   Notes:
9922   You must call `MatFactorSetSchurIS()` before calling this routine.
9923 
9924   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9925 
9926   The routine returns a the Schur Complement stored within the data structures of the solver.
9927 
9928   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9929 
9930   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9931 
9932   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9933 
9934   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9935 
9936 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9937 @*/
9938 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9939 {
9940   PetscFunctionBegin;
9941   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9942   if (S) {
9943     PetscAssertPointer(S, 2);
9944     *S = F->schur;
9945   }
9946   if (status) {
9947     PetscAssertPointer(status, 3);
9948     *status = F->schur_status;
9949   }
9950   PetscFunctionReturn(PETSC_SUCCESS);
9951 }
9952 
9953 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9954 {
9955   Mat S = F->schur;
9956 
9957   PetscFunctionBegin;
9958   switch (F->schur_status) {
9959   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9960   case MAT_FACTOR_SCHUR_INVERTED:
9961     if (S) {
9962       S->ops->solve             = NULL;
9963       S->ops->matsolve          = NULL;
9964       S->ops->solvetranspose    = NULL;
9965       S->ops->matsolvetranspose = NULL;
9966       S->ops->solveadd          = NULL;
9967       S->ops->solvetransposeadd = NULL;
9968       S->factortype             = MAT_FACTOR_NONE;
9969       PetscCall(PetscFree(S->solvertype));
9970     }
9971   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9972     break;
9973   default:
9974     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9975   }
9976   PetscFunctionReturn(PETSC_SUCCESS);
9977 }
9978 
9979 /*@
9980   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9981 
9982   Logically Collective
9983 
9984   Input Parameters:
9985 + F      - the factored matrix obtained by calling `MatGetFactor()`
9986 . S      - location where the Schur complement is stored
9987 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9988 
9989   Level: advanced
9990 
9991 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9992 @*/
9993 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9994 {
9995   PetscFunctionBegin;
9996   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9997   if (S) {
9998     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9999     *S = NULL;
10000   }
10001   F->schur_status = status;
10002   PetscCall(MatFactorUpdateSchurStatus_Private(F));
10003   PetscFunctionReturn(PETSC_SUCCESS);
10004 }
10005 
10006 /*@
10007   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
10008 
10009   Logically Collective
10010 
10011   Input Parameters:
10012 + F   - the factored matrix obtained by calling `MatGetFactor()`
10013 . rhs - location where the right-hand side of the Schur complement system is stored
10014 - sol - location where the solution of the Schur complement system has to be returned
10015 
10016   Level: advanced
10017 
10018   Notes:
10019   The sizes of the vectors should match the size of the Schur complement
10020 
10021   Must be called after `MatFactorSetSchurIS()`
10022 
10023 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
10024 @*/
10025 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
10026 {
10027   PetscFunctionBegin;
10028   PetscValidType(F, 1);
10029   PetscValidType(rhs, 2);
10030   PetscValidType(sol, 3);
10031   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10032   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10033   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10034   PetscCheckSameComm(F, 1, rhs, 2);
10035   PetscCheckSameComm(F, 1, sol, 3);
10036   PetscCall(MatFactorFactorizeSchurComplement(F));
10037   switch (F->schur_status) {
10038   case MAT_FACTOR_SCHUR_FACTORED:
10039     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
10040     break;
10041   case MAT_FACTOR_SCHUR_INVERTED:
10042     PetscCall(MatMultTranspose(F->schur, rhs, sol));
10043     break;
10044   default:
10045     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10046   }
10047   PetscFunctionReturn(PETSC_SUCCESS);
10048 }
10049 
10050 /*@
10051   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
10052 
10053   Logically Collective
10054 
10055   Input Parameters:
10056 + F   - the factored matrix obtained by calling `MatGetFactor()`
10057 . rhs - location where the right-hand side of the Schur complement system is stored
10058 - sol - location where the solution of the Schur complement system has to be returned
10059 
10060   Level: advanced
10061 
10062   Notes:
10063   The sizes of the vectors should match the size of the Schur complement
10064 
10065   Must be called after `MatFactorSetSchurIS()`
10066 
10067 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
10068 @*/
10069 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
10070 {
10071   PetscFunctionBegin;
10072   PetscValidType(F, 1);
10073   PetscValidType(rhs, 2);
10074   PetscValidType(sol, 3);
10075   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10076   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10077   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10078   PetscCheckSameComm(F, 1, rhs, 2);
10079   PetscCheckSameComm(F, 1, sol, 3);
10080   PetscCall(MatFactorFactorizeSchurComplement(F));
10081   switch (F->schur_status) {
10082   case MAT_FACTOR_SCHUR_FACTORED:
10083     PetscCall(MatSolve(F->schur, rhs, sol));
10084     break;
10085   case MAT_FACTOR_SCHUR_INVERTED:
10086     PetscCall(MatMult(F->schur, rhs, sol));
10087     break;
10088   default:
10089     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10090   }
10091   PetscFunctionReturn(PETSC_SUCCESS);
10092 }
10093 
10094 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10095 #if PetscDefined(HAVE_CUDA)
10096 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10097 #endif
10098 
10099 /* Schur status updated in the interface */
10100 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10101 {
10102   Mat S = F->schur;
10103 
10104   PetscFunctionBegin;
10105   if (S) {
10106     PetscMPIInt size;
10107     PetscBool   isdense, isdensecuda;
10108 
10109     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10110     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10111     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10112     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10113     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10114     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10115     if (isdense) {
10116       PetscCall(MatSeqDenseInvertFactors_Private(S));
10117     } else if (isdensecuda) {
10118 #if defined(PETSC_HAVE_CUDA)
10119       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10120 #endif
10121     }
10122     // HIP??????????????
10123     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10124   }
10125   PetscFunctionReturn(PETSC_SUCCESS);
10126 }
10127 
10128 /*@
10129   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10130 
10131   Logically Collective
10132 
10133   Input Parameter:
10134 . F - the factored matrix obtained by calling `MatGetFactor()`
10135 
10136   Level: advanced
10137 
10138   Notes:
10139   Must be called after `MatFactorSetSchurIS()`.
10140 
10141   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10142 
10143 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10144 @*/
10145 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10146 {
10147   PetscFunctionBegin;
10148   PetscValidType(F, 1);
10149   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10150   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10151   PetscCall(MatFactorFactorizeSchurComplement(F));
10152   PetscCall(MatFactorInvertSchurComplement_Private(F));
10153   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10154   PetscFunctionReturn(PETSC_SUCCESS);
10155 }
10156 
10157 /*@
10158   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10159 
10160   Logically Collective
10161 
10162   Input Parameter:
10163 . F - the factored matrix obtained by calling `MatGetFactor()`
10164 
10165   Level: advanced
10166 
10167   Note:
10168   Must be called after `MatFactorSetSchurIS()`
10169 
10170 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10171 @*/
10172 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10173 {
10174   MatFactorInfo info;
10175 
10176   PetscFunctionBegin;
10177   PetscValidType(F, 1);
10178   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10179   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10180   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10181   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10182   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10183     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10184   } else {
10185     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10186   }
10187   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10188   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10189   PetscFunctionReturn(PETSC_SUCCESS);
10190 }
10191 
10192 /*@
10193   MatPtAP - Creates the matrix product $C = P^T * A * P$
10194 
10195   Neighbor-wise Collective
10196 
10197   Input Parameters:
10198 + A     - the matrix
10199 . P     - the projection matrix
10200 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10201 - 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
10202           if the result is a dense matrix this is irrelevant
10203 
10204   Output Parameter:
10205 . C - the product matrix
10206 
10207   Level: intermediate
10208 
10209   Notes:
10210   C will be created and must be destroyed by the user with `MatDestroy()`.
10211 
10212   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10213 
10214   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10215 
10216   Developer Note:
10217   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10218 
10219 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10220 @*/
10221 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10222 {
10223   PetscFunctionBegin;
10224   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10225   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10226 
10227   if (scall == MAT_INITIAL_MATRIX) {
10228     PetscCall(MatProductCreate(A, P, NULL, C));
10229     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10230     PetscCall(MatProductSetAlgorithm(*C, "default"));
10231     PetscCall(MatProductSetFill(*C, fill));
10232 
10233     (*C)->product->api_user = PETSC_TRUE;
10234     PetscCall(MatProductSetFromOptions(*C));
10235     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);
10236     PetscCall(MatProductSymbolic(*C));
10237   } else { /* scall == MAT_REUSE_MATRIX */
10238     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10239   }
10240 
10241   PetscCall(MatProductNumeric(*C));
10242   (*C)->symmetric = A->symmetric;
10243   (*C)->spd       = A->spd;
10244   PetscFunctionReturn(PETSC_SUCCESS);
10245 }
10246 
10247 /*@
10248   MatRARt - Creates the matrix product $C = R * A * R^T$
10249 
10250   Neighbor-wise Collective
10251 
10252   Input Parameters:
10253 + A     - the matrix
10254 . R     - the projection matrix
10255 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10256 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10257           if the result is a dense matrix this is irrelevant
10258 
10259   Output Parameter:
10260 . C - the product matrix
10261 
10262   Level: intermediate
10263 
10264   Notes:
10265   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10266 
10267   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10268 
10269   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10270   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10271   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10272   We recommend using `MatPtAP()` when possible.
10273 
10274   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10275 
10276 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10277 @*/
10278 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10279 {
10280   PetscFunctionBegin;
10281   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10282   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10283 
10284   if (scall == MAT_INITIAL_MATRIX) {
10285     PetscCall(MatProductCreate(A, R, NULL, C));
10286     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10287     PetscCall(MatProductSetAlgorithm(*C, "default"));
10288     PetscCall(MatProductSetFill(*C, fill));
10289 
10290     (*C)->product->api_user = PETSC_TRUE;
10291     PetscCall(MatProductSetFromOptions(*C));
10292     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);
10293     PetscCall(MatProductSymbolic(*C));
10294   } else { /* scall == MAT_REUSE_MATRIX */
10295     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10296   }
10297 
10298   PetscCall(MatProductNumeric(*C));
10299   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10300   PetscFunctionReturn(PETSC_SUCCESS);
10301 }
10302 
10303 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10304 {
10305   PetscBool flg = PETSC_TRUE;
10306 
10307   PetscFunctionBegin;
10308   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10309   if (scall == MAT_INITIAL_MATRIX) {
10310     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10311     PetscCall(MatProductCreate(A, B, NULL, C));
10312     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10313     PetscCall(MatProductSetFill(*C, fill));
10314   } else { /* scall == MAT_REUSE_MATRIX */
10315     Mat_Product *product = (*C)->product;
10316 
10317     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10318     if (flg && product && product->type != ptype) {
10319       PetscCall(MatProductClear(*C));
10320       product = NULL;
10321     }
10322     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10323     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10324       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10325       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10326       product        = (*C)->product;
10327       product->fill  = fill;
10328       product->clear = PETSC_TRUE;
10329     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10330       flg = PETSC_FALSE;
10331       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10332     }
10333   }
10334   if (flg) {
10335     (*C)->product->api_user = PETSC_TRUE;
10336     PetscCall(MatProductSetType(*C, ptype));
10337     PetscCall(MatProductSetFromOptions(*C));
10338     PetscCall(MatProductSymbolic(*C));
10339   }
10340   PetscCall(MatProductNumeric(*C));
10341   PetscFunctionReturn(PETSC_SUCCESS);
10342 }
10343 
10344 /*@
10345   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10346 
10347   Neighbor-wise Collective
10348 
10349   Input Parameters:
10350 + A     - the left matrix
10351 . B     - the right matrix
10352 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10353 - 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
10354           if the result is a dense matrix this is irrelevant
10355 
10356   Output Parameter:
10357 . C - the product matrix
10358 
10359   Notes:
10360   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10361 
10362   `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
10363   call to this function with `MAT_INITIAL_MATRIX`.
10364 
10365   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10366 
10367   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`,
10368   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10369 
10370   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10371 
10372   Example of Usage:
10373 .vb
10374      MatProductCreate(A,B,NULL,&C);
10375      MatProductSetType(C,MATPRODUCT_AB);
10376      MatProductSymbolic(C);
10377      MatProductNumeric(C); // compute C=A * B
10378      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10379      MatProductNumeric(C);
10380      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10381      MatProductNumeric(C);
10382 .ve
10383 
10384   Level: intermediate
10385 
10386 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10387 @*/
10388 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10389 {
10390   PetscFunctionBegin;
10391   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10392   PetscFunctionReturn(PETSC_SUCCESS);
10393 }
10394 
10395 /*@
10396   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10397 
10398   Neighbor-wise Collective
10399 
10400   Input Parameters:
10401 + A     - the left matrix
10402 . B     - the right matrix
10403 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10404 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10405 
10406   Output Parameter:
10407 . C - the product matrix
10408 
10409   Options Database Key:
10410 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10411               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10412               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10413 
10414   Level: intermediate
10415 
10416   Notes:
10417   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10418 
10419   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10420 
10421   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10422   actually needed.
10423 
10424   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10425   and for pairs of `MATMPIDENSE` matrices.
10426 
10427   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10428 
10429   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10430 
10431 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10432 @*/
10433 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10434 {
10435   PetscFunctionBegin;
10436   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10437   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10438   PetscFunctionReturn(PETSC_SUCCESS);
10439 }
10440 
10441 /*@
10442   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10443 
10444   Neighbor-wise Collective
10445 
10446   Input Parameters:
10447 + A     - the left matrix
10448 . B     - the right matrix
10449 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10450 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10451 
10452   Output Parameter:
10453 . C - the product matrix
10454 
10455   Level: intermediate
10456 
10457   Notes:
10458   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10459 
10460   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10461 
10462   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10463 
10464   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10465   actually needed.
10466 
10467   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10468   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10469 
10470   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10471 
10472 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10473 @*/
10474 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10475 {
10476   PetscFunctionBegin;
10477   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10478   PetscFunctionReturn(PETSC_SUCCESS);
10479 }
10480 
10481 /*@
10482   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10483 
10484   Neighbor-wise Collective
10485 
10486   Input Parameters:
10487 + A     - the left matrix
10488 . B     - the middle matrix
10489 . C     - the right matrix
10490 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10491 - 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
10492           if the result is a dense matrix this is irrelevant
10493 
10494   Output Parameter:
10495 . D - the product matrix
10496 
10497   Level: intermediate
10498 
10499   Notes:
10500   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10501 
10502   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10503 
10504   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10505 
10506   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10507   actually needed.
10508 
10509   If you have many matrices with the same non-zero structure to multiply, you
10510   should use `MAT_REUSE_MATRIX` in all calls but the first
10511 
10512   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10513 
10514 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10515 @*/
10516 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10517 {
10518   PetscFunctionBegin;
10519   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10520   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10521 
10522   if (scall == MAT_INITIAL_MATRIX) {
10523     PetscCall(MatProductCreate(A, B, C, D));
10524     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10525     PetscCall(MatProductSetAlgorithm(*D, "default"));
10526     PetscCall(MatProductSetFill(*D, fill));
10527 
10528     (*D)->product->api_user = PETSC_TRUE;
10529     PetscCall(MatProductSetFromOptions(*D));
10530     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,
10531                ((PetscObject)C)->type_name);
10532     PetscCall(MatProductSymbolic(*D));
10533   } else { /* user may change input matrices when REUSE */
10534     PetscCall(MatProductReplaceMats(A, B, C, *D));
10535   }
10536   PetscCall(MatProductNumeric(*D));
10537   PetscFunctionReturn(PETSC_SUCCESS);
10538 }
10539 
10540 /*@
10541   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10542 
10543   Collective
10544 
10545   Input Parameters:
10546 + mat      - the matrix
10547 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10548 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10549 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10550 
10551   Output Parameter:
10552 . matredundant - redundant matrix
10553 
10554   Level: advanced
10555 
10556   Notes:
10557   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10558   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10559 
10560   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10561   calling it.
10562 
10563   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10564 
10565 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10566 @*/
10567 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10568 {
10569   MPI_Comm       comm;
10570   PetscMPIInt    size;
10571   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10572   Mat_Redundant *redund     = NULL;
10573   PetscSubcomm   psubcomm   = NULL;
10574   MPI_Comm       subcomm_in = subcomm;
10575   Mat           *matseq;
10576   IS             isrow, iscol;
10577   PetscBool      newsubcomm = PETSC_FALSE;
10578 
10579   PetscFunctionBegin;
10580   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10581   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10582     PetscAssertPointer(*matredundant, 5);
10583     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10584   }
10585 
10586   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10587   if (size == 1 || nsubcomm == 1) {
10588     if (reuse == MAT_INITIAL_MATRIX) {
10589       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10590     } else {
10591       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");
10592       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10593     }
10594     PetscFunctionReturn(PETSC_SUCCESS);
10595   }
10596 
10597   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10598   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10599   MatCheckPreallocated(mat, 1);
10600 
10601   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10602   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10603     /* create psubcomm, then get subcomm */
10604     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10605     PetscCallMPI(MPI_Comm_size(comm, &size));
10606     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10607 
10608     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10609     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10610     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10611     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10612     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10613     newsubcomm = PETSC_TRUE;
10614     PetscCall(PetscSubcommDestroy(&psubcomm));
10615   }
10616 
10617   /* get isrow, iscol and a local sequential matrix matseq[0] */
10618   if (reuse == MAT_INITIAL_MATRIX) {
10619     mloc_sub = PETSC_DECIDE;
10620     nloc_sub = PETSC_DECIDE;
10621     if (bs < 1) {
10622       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10623       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10624     } else {
10625       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10626       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10627     }
10628     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10629     rstart = rend - mloc_sub;
10630     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10631     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10632     PetscCall(ISSetIdentity(iscol));
10633   } else { /* reuse == MAT_REUSE_MATRIX */
10634     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");
10635     /* retrieve subcomm */
10636     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10637     redund = (*matredundant)->redundant;
10638     isrow  = redund->isrow;
10639     iscol  = redund->iscol;
10640     matseq = redund->matseq;
10641   }
10642   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10643 
10644   /* get matredundant over subcomm */
10645   if (reuse == MAT_INITIAL_MATRIX) {
10646     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10647 
10648     /* create a supporting struct and attach it to C for reuse */
10649     PetscCall(PetscNew(&redund));
10650     (*matredundant)->redundant = redund;
10651     redund->isrow              = isrow;
10652     redund->iscol              = iscol;
10653     redund->matseq             = matseq;
10654     if (newsubcomm) {
10655       redund->subcomm = subcomm;
10656     } else {
10657       redund->subcomm = MPI_COMM_NULL;
10658     }
10659   } else {
10660     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10661   }
10662 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10663   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10664     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10665     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10666   }
10667 #endif
10668   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10669   PetscFunctionReturn(PETSC_SUCCESS);
10670 }
10671 
10672 /*@C
10673   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10674   a given `Mat`. Each submatrix can span multiple procs.
10675 
10676   Collective
10677 
10678   Input Parameters:
10679 + mat     - the matrix
10680 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10681 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10682 
10683   Output Parameter:
10684 . subMat - parallel sub-matrices each spanning a given `subcomm`
10685 
10686   Level: advanced
10687 
10688   Notes:
10689   The submatrix partition across processors is dictated by `subComm` a
10690   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10691   is not restricted to be grouped with consecutive original MPI processes.
10692 
10693   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10694   map directly to the layout of the original matrix [wrt the local
10695   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10696   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10697   the `subMat`. However the offDiagMat looses some columns - and this is
10698   reconstructed with `MatSetValues()`
10699 
10700   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10701 
10702 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10703 @*/
10704 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10705 {
10706   PetscMPIInt commsize, subCommSize;
10707 
10708   PetscFunctionBegin;
10709   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10710   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10711   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10712 
10713   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");
10714   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10715   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10716   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10717   PetscFunctionReturn(PETSC_SUCCESS);
10718 }
10719 
10720 /*@
10721   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10722 
10723   Not Collective
10724 
10725   Input Parameters:
10726 + mat   - matrix to extract local submatrix from
10727 . isrow - local row indices for submatrix
10728 - iscol - local column indices for submatrix
10729 
10730   Output Parameter:
10731 . submat - the submatrix
10732 
10733   Level: intermediate
10734 
10735   Notes:
10736   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10737 
10738   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10739   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10740 
10741   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10742   `MatSetValuesBlockedLocal()` will also be implemented.
10743 
10744   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10745   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10746 
10747 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10748 @*/
10749 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10750 {
10751   PetscFunctionBegin;
10752   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10753   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10754   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10755   PetscCheckSameComm(isrow, 2, iscol, 3);
10756   PetscAssertPointer(submat, 4);
10757   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10758 
10759   if (mat->ops->getlocalsubmatrix) {
10760     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10761   } else {
10762     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10763   }
10764   PetscFunctionReturn(PETSC_SUCCESS);
10765 }
10766 
10767 /*@
10768   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10769 
10770   Not Collective
10771 
10772   Input Parameters:
10773 + mat    - matrix to extract local submatrix from
10774 . isrow  - local row indices for submatrix
10775 . iscol  - local column indices for submatrix
10776 - submat - the submatrix
10777 
10778   Level: intermediate
10779 
10780 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10781 @*/
10782 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10783 {
10784   PetscFunctionBegin;
10785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10786   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10787   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10788   PetscCheckSameComm(isrow, 2, iscol, 3);
10789   PetscAssertPointer(submat, 4);
10790   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10791 
10792   if (mat->ops->restorelocalsubmatrix) {
10793     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10794   } else {
10795     PetscCall(MatDestroy(submat));
10796   }
10797   *submat = NULL;
10798   PetscFunctionReturn(PETSC_SUCCESS);
10799 }
10800 
10801 /*@
10802   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10803 
10804   Collective
10805 
10806   Input Parameter:
10807 . mat - the matrix
10808 
10809   Output Parameter:
10810 . is - if any rows have zero diagonals this contains the list of them
10811 
10812   Level: developer
10813 
10814 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10815 @*/
10816 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10817 {
10818   PetscFunctionBegin;
10819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10820   PetscValidType(mat, 1);
10821   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10822   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10823 
10824   if (!mat->ops->findzerodiagonals) {
10825     Vec                diag;
10826     const PetscScalar *a;
10827     PetscInt          *rows;
10828     PetscInt           rStart, rEnd, r, nrow = 0;
10829 
10830     PetscCall(MatCreateVecs(mat, &diag, NULL));
10831     PetscCall(MatGetDiagonal(mat, diag));
10832     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10833     PetscCall(VecGetArrayRead(diag, &a));
10834     for (r = 0; r < rEnd - rStart; ++r)
10835       if (a[r] == 0.0) ++nrow;
10836     PetscCall(PetscMalloc1(nrow, &rows));
10837     nrow = 0;
10838     for (r = 0; r < rEnd - rStart; ++r)
10839       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10840     PetscCall(VecRestoreArrayRead(diag, &a));
10841     PetscCall(VecDestroy(&diag));
10842     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10843   } else {
10844     PetscUseTypeMethod(mat, findzerodiagonals, is);
10845   }
10846   PetscFunctionReturn(PETSC_SUCCESS);
10847 }
10848 
10849 /*@
10850   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10851 
10852   Collective
10853 
10854   Input Parameter:
10855 . mat - the matrix
10856 
10857   Output Parameter:
10858 . is - contains the list of rows with off block diagonal entries
10859 
10860   Level: developer
10861 
10862 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10863 @*/
10864 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10865 {
10866   PetscFunctionBegin;
10867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10868   PetscValidType(mat, 1);
10869   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10870   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10871 
10872   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10873   PetscFunctionReturn(PETSC_SUCCESS);
10874 }
10875 
10876 /*@C
10877   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10878 
10879   Collective; No Fortran Support
10880 
10881   Input Parameter:
10882 . mat - the matrix
10883 
10884   Output Parameter:
10885 . values - the block inverses in column major order (FORTRAN-like)
10886 
10887   Level: advanced
10888 
10889   Notes:
10890   The size of the blocks is determined by the block size of the matrix.
10891 
10892   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10893 
10894   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10895 
10896 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10897 @*/
10898 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10899 {
10900   PetscFunctionBegin;
10901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10902   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10903   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10904   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10905   PetscFunctionReturn(PETSC_SUCCESS);
10906 }
10907 
10908 /*@
10909   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10910 
10911   Collective; No Fortran Support
10912 
10913   Input Parameters:
10914 + mat     - the matrix
10915 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10916 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10917 
10918   Output Parameter:
10919 . values - the block inverses in column major order (FORTRAN-like)
10920 
10921   Level: advanced
10922 
10923   Notes:
10924   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10925 
10926   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10927 
10928 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10929 @*/
10930 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10931 {
10932   PetscFunctionBegin;
10933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10934   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10935   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10936   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10937   PetscFunctionReturn(PETSC_SUCCESS);
10938 }
10939 
10940 /*@
10941   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10942 
10943   Collective
10944 
10945   Input Parameters:
10946 + A - the matrix
10947 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10948 
10949   Level: advanced
10950 
10951   Note:
10952   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10953 
10954 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10955 @*/
10956 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10957 {
10958   const PetscScalar *vals;
10959   PetscInt          *dnnz;
10960   PetscInt           m, rstart, rend, bs, i, j;
10961 
10962   PetscFunctionBegin;
10963   PetscCall(MatInvertBlockDiagonal(A, &vals));
10964   PetscCall(MatGetBlockSize(A, &bs));
10965   PetscCall(MatGetLocalSize(A, &m, NULL));
10966   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10967   PetscCall(PetscMalloc1(m / bs, &dnnz));
10968   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10969   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10970   PetscCall(PetscFree(dnnz));
10971   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10972   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10973   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10974   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10975   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10976   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10977   PetscFunctionReturn(PETSC_SUCCESS);
10978 }
10979 
10980 /*@
10981   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10982   via `MatTransposeColoringCreate()`.
10983 
10984   Collective
10985 
10986   Input Parameter:
10987 . c - coloring context
10988 
10989   Level: intermediate
10990 
10991 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10992 @*/
10993 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10994 {
10995   MatTransposeColoring matcolor = *c;
10996 
10997   PetscFunctionBegin;
10998   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10999   if (--((PetscObject)matcolor)->refct > 0) {
11000     matcolor = NULL;
11001     PetscFunctionReturn(PETSC_SUCCESS);
11002   }
11003 
11004   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
11005   PetscCall(PetscFree(matcolor->rows));
11006   PetscCall(PetscFree(matcolor->den2sp));
11007   PetscCall(PetscFree(matcolor->colorforcol));
11008   PetscCall(PetscFree(matcolor->columns));
11009   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
11010   PetscCall(PetscHeaderDestroy(c));
11011   PetscFunctionReturn(PETSC_SUCCESS);
11012 }
11013 
11014 /*@
11015   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
11016   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
11017   `MatTransposeColoring` to sparse `B`.
11018 
11019   Collective
11020 
11021   Input Parameters:
11022 + coloring - coloring context created with `MatTransposeColoringCreate()`
11023 - B        - sparse matrix
11024 
11025   Output Parameter:
11026 . Btdense - dense matrix $B^T$
11027 
11028   Level: developer
11029 
11030   Note:
11031   These are used internally for some implementations of `MatRARt()`
11032 
11033 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
11034 @*/
11035 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
11036 {
11037   PetscFunctionBegin;
11038   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11039   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
11040   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
11041 
11042   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
11043   PetscFunctionReturn(PETSC_SUCCESS);
11044 }
11045 
11046 /*@
11047   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
11048   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
11049   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
11050   $C_{sp}$ from $C_{den}$.
11051 
11052   Collective
11053 
11054   Input Parameters:
11055 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
11056 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
11057 
11058   Output Parameter:
11059 . Csp - sparse matrix
11060 
11061   Level: developer
11062 
11063   Note:
11064   These are used internally for some implementations of `MatRARt()`
11065 
11066 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
11067 @*/
11068 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
11069 {
11070   PetscFunctionBegin;
11071   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11072   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
11073   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
11074 
11075   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
11076   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
11077   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
11078   PetscFunctionReturn(PETSC_SUCCESS);
11079 }
11080 
11081 /*@
11082   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
11083 
11084   Collective
11085 
11086   Input Parameters:
11087 + mat        - the matrix product C
11088 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
11089 
11090   Output Parameter:
11091 . color - the new coloring context
11092 
11093   Level: intermediate
11094 
11095 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11096           `MatTransColoringApplyDenToSp()`
11097 @*/
11098 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11099 {
11100   MatTransposeColoring c;
11101   MPI_Comm             comm;
11102 
11103   PetscFunctionBegin;
11104   PetscAssertPointer(color, 3);
11105 
11106   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11107   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11108   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11109   c->ctype = iscoloring->ctype;
11110   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11111   *color = c;
11112   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11113   PetscFunctionReturn(PETSC_SUCCESS);
11114 }
11115 
11116 /*@
11117   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11118   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11119 
11120   Not Collective
11121 
11122   Input Parameter:
11123 . mat - the matrix
11124 
11125   Output Parameter:
11126 . state - the current state
11127 
11128   Level: intermediate
11129 
11130   Notes:
11131   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11132   different matrices
11133 
11134   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11135 
11136   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11137 
11138 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11139 @*/
11140 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11141 {
11142   PetscFunctionBegin;
11143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11144   *state = mat->nonzerostate;
11145   PetscFunctionReturn(PETSC_SUCCESS);
11146 }
11147 
11148 /*@
11149   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11150   matrices from each processor
11151 
11152   Collective
11153 
11154   Input Parameters:
11155 + comm   - the communicators the parallel matrix will live on
11156 . seqmat - the input sequential matrices
11157 . n      - number of local columns (or `PETSC_DECIDE`)
11158 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11159 
11160   Output Parameter:
11161 . mpimat - the parallel matrix generated
11162 
11163   Level: developer
11164 
11165   Note:
11166   The number of columns of the matrix in EACH processor MUST be the same.
11167 
11168 .seealso: [](ch_matrices), `Mat`
11169 @*/
11170 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11171 {
11172   PetscMPIInt size;
11173 
11174   PetscFunctionBegin;
11175   PetscCallMPI(MPI_Comm_size(comm, &size));
11176   if (size == 1) {
11177     if (reuse == MAT_INITIAL_MATRIX) {
11178       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11179     } else {
11180       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11181     }
11182     PetscFunctionReturn(PETSC_SUCCESS);
11183   }
11184 
11185   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");
11186 
11187   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11188   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11189   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11190   PetscFunctionReturn(PETSC_SUCCESS);
11191 }
11192 
11193 /*@
11194   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11195 
11196   Collective
11197 
11198   Input Parameters:
11199 + A - the matrix to create subdomains from
11200 - N - requested number of subdomains
11201 
11202   Output Parameters:
11203 + n   - number of subdomains resulting on this MPI process
11204 - iss - `IS` list with indices of subdomains on this MPI process
11205 
11206   Level: advanced
11207 
11208   Note:
11209   The number of subdomains must be smaller than the communicator size
11210 
11211 .seealso: [](ch_matrices), `Mat`, `IS`
11212 @*/
11213 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11214 {
11215   MPI_Comm    comm, subcomm;
11216   PetscMPIInt size, rank, color;
11217   PetscInt    rstart, rend, k;
11218 
11219   PetscFunctionBegin;
11220   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11221   PetscCallMPI(MPI_Comm_size(comm, &size));
11222   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11223   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);
11224   *n    = 1;
11225   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
11226   color = rank / k;
11227   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11228   PetscCall(PetscMalloc1(1, iss));
11229   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11230   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11231   PetscCallMPI(MPI_Comm_free(&subcomm));
11232   PetscFunctionReturn(PETSC_SUCCESS);
11233 }
11234 
11235 /*@
11236   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11237 
11238   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11239   If they are not the same, uses `MatMatMatMult()`.
11240 
11241   Once the coarse grid problem is constructed, correct for interpolation operators
11242   that are not of full rank, which can legitimately happen in the case of non-nested
11243   geometric multigrid.
11244 
11245   Input Parameters:
11246 + restrct     - restriction operator
11247 . dA          - fine grid matrix
11248 . interpolate - interpolation operator
11249 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11250 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11251 
11252   Output Parameter:
11253 . A - the Galerkin coarse matrix
11254 
11255   Options Database Key:
11256 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11257 
11258   Level: developer
11259 
11260   Note:
11261   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11262 
11263 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11264 @*/
11265 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11266 {
11267   IS  zerorows;
11268   Vec diag;
11269 
11270   PetscFunctionBegin;
11271   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11272   /* Construct the coarse grid matrix */
11273   if (interpolate == restrct) {
11274     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11275   } else {
11276     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11277   }
11278 
11279   /* If the interpolation matrix is not of full rank, A will have zero rows.
11280      This can legitimately happen in the case of non-nested geometric multigrid.
11281      In that event, we set the rows of the matrix to the rows of the identity,
11282      ignoring the equations (as the RHS will also be zero). */
11283 
11284   PetscCall(MatFindZeroRows(*A, &zerorows));
11285 
11286   if (zerorows != NULL) { /* if there are any zero rows */
11287     PetscCall(MatCreateVecs(*A, &diag, NULL));
11288     PetscCall(MatGetDiagonal(*A, diag));
11289     PetscCall(VecISSet(diag, zerorows, 1.0));
11290     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11291     PetscCall(VecDestroy(&diag));
11292     PetscCall(ISDestroy(&zerorows));
11293   }
11294   PetscFunctionReturn(PETSC_SUCCESS);
11295 }
11296 
11297 /*@C
11298   MatSetOperation - Allows user to set a matrix operation for any matrix type
11299 
11300   Logically Collective
11301 
11302   Input Parameters:
11303 + mat - the matrix
11304 . op  - the name of the operation
11305 - f   - the function that provides the operation
11306 
11307   Level: developer
11308 
11309   Example Usage:
11310 .vb
11311   extern PetscErrorCode usermult(Mat, Vec, Vec);
11312 
11313   PetscCall(MatCreateXXX(comm, ..., &A));
11314   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11315 .ve
11316 
11317   Notes:
11318   See the file `include/petscmat.h` for a complete list of matrix
11319   operations, which all have the form MATOP_<OPERATION>, where
11320   <OPERATION> is the name (in all capital letters) of the
11321   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11322 
11323   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11324   sequence as the usual matrix interface routines, since they
11325   are intended to be accessed via the usual matrix interface
11326   routines, e.g.,
11327 .vb
11328   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11329 .ve
11330 
11331   In particular each function MUST return `PETSC_SUCCESS` on success and
11332   nonzero on failure.
11333 
11334   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11335 
11336 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11337 @*/
11338 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11339 {
11340   PetscFunctionBegin;
11341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11342   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11343   (((void (**)(void))mat->ops)[op]) = f;
11344   PetscFunctionReturn(PETSC_SUCCESS);
11345 }
11346 
11347 /*@C
11348   MatGetOperation - Gets a matrix operation for any matrix type.
11349 
11350   Not Collective
11351 
11352   Input Parameters:
11353 + mat - the matrix
11354 - op  - the name of the operation
11355 
11356   Output Parameter:
11357 . f - the function that provides the operation
11358 
11359   Level: developer
11360 
11361   Example Usage:
11362 .vb
11363   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11364 
11365   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11366 .ve
11367 
11368   Notes:
11369   See the file include/petscmat.h for a complete list of matrix
11370   operations, which all have the form MATOP_<OPERATION>, where
11371   <OPERATION> is the name (in all capital letters) of the
11372   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11373 
11374   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11375 
11376 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11377 @*/
11378 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11379 {
11380   PetscFunctionBegin;
11381   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11382   *f = (((void (**)(void))mat->ops)[op]);
11383   PetscFunctionReturn(PETSC_SUCCESS);
11384 }
11385 
11386 /*@
11387   MatHasOperation - Determines whether the given matrix supports the particular operation.
11388 
11389   Not Collective
11390 
11391   Input Parameters:
11392 + mat - the matrix
11393 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11394 
11395   Output Parameter:
11396 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11397 
11398   Level: advanced
11399 
11400   Note:
11401   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11402 
11403 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11404 @*/
11405 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11406 {
11407   PetscFunctionBegin;
11408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11409   PetscAssertPointer(has, 3);
11410   if (mat->ops->hasoperation) {
11411     PetscUseTypeMethod(mat, hasoperation, op, has);
11412   } else {
11413     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11414     else {
11415       *has = PETSC_FALSE;
11416       if (op == MATOP_CREATE_SUBMATRIX) {
11417         PetscMPIInt size;
11418 
11419         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11420         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11421       }
11422     }
11423   }
11424   PetscFunctionReturn(PETSC_SUCCESS);
11425 }
11426 
11427 /*@
11428   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11429 
11430   Collective
11431 
11432   Input Parameter:
11433 . mat - the matrix
11434 
11435   Output Parameter:
11436 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11437 
11438   Level: beginner
11439 
11440 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11441 @*/
11442 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11443 {
11444   PetscFunctionBegin;
11445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11446   PetscValidType(mat, 1);
11447   PetscAssertPointer(cong, 2);
11448   if (!mat->rmap || !mat->cmap) {
11449     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11450     PetscFunctionReturn(PETSC_SUCCESS);
11451   }
11452   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11453     PetscCall(PetscLayoutSetUp(mat->rmap));
11454     PetscCall(PetscLayoutSetUp(mat->cmap));
11455     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11456     if (*cong) mat->congruentlayouts = 1;
11457     else mat->congruentlayouts = 0;
11458   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11459   PetscFunctionReturn(PETSC_SUCCESS);
11460 }
11461 
11462 PetscErrorCode MatSetInf(Mat A)
11463 {
11464   PetscFunctionBegin;
11465   PetscUseTypeMethod(A, setinf);
11466   PetscFunctionReturn(PETSC_SUCCESS);
11467 }
11468 
11469 /*@
11470   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
11471   and possibly removes small values from the graph structure.
11472 
11473   Collective
11474 
11475   Input Parameters:
11476 + A       - the matrix
11477 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11478 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11479 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11480 . num_idx - size of 'index' array
11481 - index   - array of block indices to use for graph strength of connection weight
11482 
11483   Output Parameter:
11484 . graph - the resulting graph
11485 
11486   Level: advanced
11487 
11488 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11489 @*/
11490 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11491 {
11492   PetscFunctionBegin;
11493   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11494   PetscValidType(A, 1);
11495   PetscValidLogicalCollectiveBool(A, scale, 3);
11496   PetscAssertPointer(graph, 7);
11497   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11498   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11499   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11500   PetscFunctionReturn(PETSC_SUCCESS);
11501 }
11502 
11503 /*@
11504   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11505   meaning the same memory is used for the matrix, and no new memory is allocated.
11506 
11507   Collective
11508 
11509   Input Parameters:
11510 + A    - the matrix
11511 - 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
11512 
11513   Level: intermediate
11514 
11515   Developer Note:
11516   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11517   of the arrays in the data structure are unneeded.
11518 
11519 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11520 @*/
11521 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11522 {
11523   PetscFunctionBegin;
11524   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11525   PetscUseTypeMethod(A, eliminatezeros, keep);
11526   PetscFunctionReturn(PETSC_SUCCESS);
11527 }
11528