xref: /petsc/src/mat/interface/matrix.c (revision 3fed57382a69ddef8b301aa4ce9b2f05bf867c00)
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   Note:
5681   If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product
5682   using several randomly created vectors, see `MatMultEqual()`.
5683 
5684 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5685 @*/
5686 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5687 {
5688   PetscFunctionBegin;
5689   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5690   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5691   PetscValidType(A, 1);
5692   PetscValidType(B, 2);
5693   PetscAssertPointer(flg, 3);
5694   PetscCheckSameComm(A, 1, B, 2);
5695   MatCheckPreallocated(A, 1);
5696   MatCheckPreallocated(B, 2);
5697   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5698   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5699   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,
5700              B->cmap->N);
5701   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5702     PetscUseTypeMethod(A, equal, B, flg);
5703   } else {
5704     PetscCall(MatMultEqual(A, B, 10, flg));
5705   }
5706   PetscFunctionReturn(PETSC_SUCCESS);
5707 }
5708 
5709 /*@
5710   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5711   matrices that are stored as vectors.  Either of the two scaling
5712   matrices can be `NULL`.
5713 
5714   Collective
5715 
5716   Input Parameters:
5717 + mat - the matrix to be scaled
5718 . l   - the left scaling vector (or `NULL`)
5719 - r   - the right scaling vector (or `NULL`)
5720 
5721   Level: intermediate
5722 
5723   Note:
5724   `MatDiagonalScale()` computes $A = LAR$, where
5725   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5726   The L scales the rows of the matrix, the R scales the columns of the matrix.
5727 
5728 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5729 @*/
5730 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5731 {
5732   PetscFunctionBegin;
5733   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5734   PetscValidType(mat, 1);
5735   if (l) {
5736     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5737     PetscCheckSameComm(mat, 1, l, 2);
5738   }
5739   if (r) {
5740     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5741     PetscCheckSameComm(mat, 1, r, 3);
5742   }
5743   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5744   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5745   MatCheckPreallocated(mat, 1);
5746   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5747 
5748   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5749   PetscUseTypeMethod(mat, diagonalscale, l, r);
5750   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5751   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5752   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5753   PetscFunctionReturn(PETSC_SUCCESS);
5754 }
5755 
5756 /*@
5757   MatScale - Scales all elements of a matrix by a given number.
5758 
5759   Logically Collective
5760 
5761   Input Parameters:
5762 + mat - the matrix to be scaled
5763 - a   - the scaling value
5764 
5765   Level: intermediate
5766 
5767 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5768 @*/
5769 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5770 {
5771   PetscFunctionBegin;
5772   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5773   PetscValidType(mat, 1);
5774   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5775   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5776   PetscValidLogicalCollectiveScalar(mat, a, 2);
5777   MatCheckPreallocated(mat, 1);
5778 
5779   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5780   if (a != (PetscScalar)1.0) {
5781     PetscUseTypeMethod(mat, scale, a);
5782     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5783   }
5784   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5785   PetscFunctionReturn(PETSC_SUCCESS);
5786 }
5787 
5788 /*@
5789   MatNorm - Calculates various norms of a matrix.
5790 
5791   Collective
5792 
5793   Input Parameters:
5794 + mat  - the matrix
5795 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5796 
5797   Output Parameter:
5798 . nrm - the resulting norm
5799 
5800   Level: intermediate
5801 
5802 .seealso: [](ch_matrices), `Mat`
5803 @*/
5804 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5805 {
5806   PetscFunctionBegin;
5807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5808   PetscValidType(mat, 1);
5809   PetscAssertPointer(nrm, 3);
5810 
5811   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5812   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5813   MatCheckPreallocated(mat, 1);
5814 
5815   PetscUseTypeMethod(mat, norm, type, nrm);
5816   PetscFunctionReturn(PETSC_SUCCESS);
5817 }
5818 
5819 /*
5820      This variable is used to prevent counting of MatAssemblyBegin() that
5821    are called from within a MatAssemblyEnd().
5822 */
5823 static PetscInt MatAssemblyEnd_InUse = 0;
5824 /*@
5825   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5826   be called after completing all calls to `MatSetValues()`.
5827 
5828   Collective
5829 
5830   Input Parameters:
5831 + mat  - the matrix
5832 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5833 
5834   Level: beginner
5835 
5836   Notes:
5837   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5838   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5839 
5840   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5841   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5842   using the matrix.
5843 
5844   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5845   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
5846   a global collective operation requiring all processes that share the matrix.
5847 
5848   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5849   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5850   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5851 
5852 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5853 @*/
5854 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5855 {
5856   PetscFunctionBegin;
5857   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5858   PetscValidType(mat, 1);
5859   MatCheckPreallocated(mat, 1);
5860   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5861   if (mat->assembled) {
5862     mat->was_assembled = PETSC_TRUE;
5863     mat->assembled     = PETSC_FALSE;
5864   }
5865 
5866   if (!MatAssemblyEnd_InUse) {
5867     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5868     PetscTryTypeMethod(mat, assemblybegin, type);
5869     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5870   } else PetscTryTypeMethod(mat, assemblybegin, type);
5871   PetscFunctionReturn(PETSC_SUCCESS);
5872 }
5873 
5874 /*@
5875   MatAssembled - Indicates if a matrix has been assembled and is ready for
5876   use; for example, in matrix-vector product.
5877 
5878   Not Collective
5879 
5880   Input Parameter:
5881 . mat - the matrix
5882 
5883   Output Parameter:
5884 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5885 
5886   Level: advanced
5887 
5888 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5889 @*/
5890 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5891 {
5892   PetscFunctionBegin;
5893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5894   PetscAssertPointer(assembled, 2);
5895   *assembled = mat->assembled;
5896   PetscFunctionReturn(PETSC_SUCCESS);
5897 }
5898 
5899 /*@
5900   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5901   be called after `MatAssemblyBegin()`.
5902 
5903   Collective
5904 
5905   Input Parameters:
5906 + mat  - the matrix
5907 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5908 
5909   Options Database Keys:
5910 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5911 . -mat_view ::ascii_info_detail      - Prints more detailed info
5912 . -mat_view                          - Prints matrix in ASCII format
5913 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5914 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5915 . -display <name>                    - Sets display name (default is host)
5916 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5917 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5918 . -viewer_socket_machine <machine>   - Machine to use for socket
5919 . -viewer_socket_port <port>         - Port number to use for socket
5920 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5921 
5922   Level: beginner
5923 
5924 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5925 @*/
5926 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5927 {
5928   static PetscInt inassm = 0;
5929   PetscBool       flg    = PETSC_FALSE;
5930 
5931   PetscFunctionBegin;
5932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5933   PetscValidType(mat, 1);
5934 
5935   inassm++;
5936   MatAssemblyEnd_InUse++;
5937   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5938     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5939     PetscTryTypeMethod(mat, assemblyend, type);
5940     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5941   } else PetscTryTypeMethod(mat, assemblyend, type);
5942 
5943   /* Flush assembly is not a true assembly */
5944   if (type != MAT_FLUSH_ASSEMBLY) {
5945     if (mat->num_ass) {
5946       if (!mat->symmetry_eternal) {
5947         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5948         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5949       }
5950       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5951       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5952     }
5953     mat->num_ass++;
5954     mat->assembled        = PETSC_TRUE;
5955     mat->ass_nonzerostate = mat->nonzerostate;
5956   }
5957 
5958   mat->insertmode = NOT_SET_VALUES;
5959   MatAssemblyEnd_InUse--;
5960   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5961   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5962     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5963 
5964     if (mat->checksymmetryonassembly) {
5965       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5966       if (flg) {
5967         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5968       } else {
5969         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5970       }
5971     }
5972     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5973   }
5974   inassm--;
5975   PetscFunctionReturn(PETSC_SUCCESS);
5976 }
5977 
5978 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5979 /*@
5980   MatSetOption - Sets a parameter option for a matrix. Some options
5981   may be specific to certain storage formats.  Some options
5982   determine how values will be inserted (or added). Sorted,
5983   row-oriented input will generally assemble the fastest. The default
5984   is row-oriented.
5985 
5986   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5987 
5988   Input Parameters:
5989 + mat - the matrix
5990 . op  - the option, one of those listed below (and possibly others),
5991 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5992 
5993   Options Describing Matrix Structure:
5994 + `MAT_SPD`                         - symmetric positive definite
5995 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5996 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5997 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5998 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5999 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
6000 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
6001 
6002    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
6003    do not need to be computed (usually at a high cost)
6004 
6005    Options For Use with `MatSetValues()`:
6006    Insert a logically dense subblock, which can be
6007 . `MAT_ROW_ORIENTED`                - row-oriented (default)
6008 
6009    These options reflect the data you pass in with `MatSetValues()`; it has
6010    nothing to do with how the data is stored internally in the matrix
6011    data structure.
6012 
6013    When (re)assembling a matrix, we can restrict the input for
6014    efficiency/debugging purposes.  These options include
6015 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
6016 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
6017 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
6018 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
6019 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
6020 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
6021         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
6022         performance for very large process counts.
6023 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
6024         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
6025         functions, instead sending only neighbor messages.
6026 
6027   Level: intermediate
6028 
6029   Notes:
6030   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
6031 
6032   Some options are relevant only for particular matrix types and
6033   are thus ignored by others.  Other options are not supported by
6034   certain matrix types and will generate an error message if set.
6035 
6036   If using Fortran to compute a matrix, one may need to
6037   use the column-oriented option (or convert to the row-oriented
6038   format).
6039 
6040   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
6041   that would generate a new entry in the nonzero structure is instead
6042   ignored.  Thus, if memory has not already been allocated for this particular
6043   data, then the insertion is ignored. For dense matrices, in which
6044   the entire array is allocated, no entries are ever ignored.
6045   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6046 
6047   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6048   that would generate a new entry in the nonzero structure instead produces
6049   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
6050 
6051   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6052   that would generate a new entry that has not been preallocated will
6053   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6054   only.) This is a useful flag when debugging matrix memory preallocation.
6055   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6056 
6057   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6058   other processors should be dropped, rather than stashed.
6059   This is useful if you know that the "owning" processor is also
6060   always generating the correct matrix entries, so that PETSc need
6061   not transfer duplicate entries generated on another processor.
6062 
6063   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6064   searches during matrix assembly. When this flag is set, the hash table
6065   is created during the first matrix assembly. This hash table is
6066   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6067   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6068   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6069   supported by `MATMPIBAIJ` format only.
6070 
6071   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6072   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6073 
6074   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6075   a zero location in the matrix
6076 
6077   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6078 
6079   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6080   zero row routines and thus improves performance for very large process counts.
6081 
6082   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6083   part of the matrix (since they should match the upper triangular part).
6084 
6085   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6086   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6087   with finite difference schemes with non-periodic boundary conditions.
6088 
6089   Developer Note:
6090   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6091   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6092   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6093   not changed.
6094 
6095 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6096 @*/
6097 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6098 {
6099   PetscFunctionBegin;
6100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6101   if (op > 0) {
6102     PetscValidLogicalCollectiveEnum(mat, op, 2);
6103     PetscValidLogicalCollectiveBool(mat, flg, 3);
6104   }
6105 
6106   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);
6107 
6108   switch (op) {
6109   case MAT_FORCE_DIAGONAL_ENTRIES:
6110     mat->force_diagonals = flg;
6111     PetscFunctionReturn(PETSC_SUCCESS);
6112   case MAT_NO_OFF_PROC_ENTRIES:
6113     mat->nooffprocentries = flg;
6114     PetscFunctionReturn(PETSC_SUCCESS);
6115   case MAT_SUBSET_OFF_PROC_ENTRIES:
6116     mat->assembly_subset = flg;
6117     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6118 #if !defined(PETSC_HAVE_MPIUNI)
6119       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6120 #endif
6121       mat->stash.first_assembly_done = PETSC_FALSE;
6122     }
6123     PetscFunctionReturn(PETSC_SUCCESS);
6124   case MAT_NO_OFF_PROC_ZERO_ROWS:
6125     mat->nooffproczerorows = flg;
6126     PetscFunctionReturn(PETSC_SUCCESS);
6127   case MAT_SPD:
6128     if (flg) {
6129       mat->spd                    = PETSC_BOOL3_TRUE;
6130       mat->symmetric              = PETSC_BOOL3_TRUE;
6131       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6132     } else {
6133       mat->spd = PETSC_BOOL3_FALSE;
6134     }
6135     break;
6136   case MAT_SYMMETRIC:
6137     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6138     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6139 #if !defined(PETSC_USE_COMPLEX)
6140     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6141 #endif
6142     break;
6143   case MAT_HERMITIAN:
6144     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6145     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6146 #if !defined(PETSC_USE_COMPLEX)
6147     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6148 #endif
6149     break;
6150   case MAT_STRUCTURALLY_SYMMETRIC:
6151     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6152     break;
6153   case MAT_SYMMETRY_ETERNAL:
6154     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");
6155     mat->symmetry_eternal = flg;
6156     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6157     break;
6158   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6159     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");
6160     mat->structural_symmetry_eternal = flg;
6161     break;
6162   case MAT_SPD_ETERNAL:
6163     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");
6164     mat->spd_eternal = flg;
6165     if (flg) {
6166       mat->structural_symmetry_eternal = PETSC_TRUE;
6167       mat->symmetry_eternal            = PETSC_TRUE;
6168     }
6169     break;
6170   case MAT_STRUCTURE_ONLY:
6171     mat->structure_only = flg;
6172     break;
6173   case MAT_SORTED_FULL:
6174     mat->sortedfull = flg;
6175     break;
6176   default:
6177     break;
6178   }
6179   PetscTryTypeMethod(mat, setoption, op, flg);
6180   PetscFunctionReturn(PETSC_SUCCESS);
6181 }
6182 
6183 /*@
6184   MatGetOption - Gets a parameter option that has been set for a matrix.
6185 
6186   Logically Collective
6187 
6188   Input Parameters:
6189 + mat - the matrix
6190 - op  - the option, this only responds to certain options, check the code for which ones
6191 
6192   Output Parameter:
6193 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6194 
6195   Level: intermediate
6196 
6197   Notes:
6198   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6199 
6200   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6201   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6202 
6203 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6204     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6205 @*/
6206 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6207 {
6208   PetscFunctionBegin;
6209   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6210   PetscValidType(mat, 1);
6211 
6212   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);
6213   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()");
6214 
6215   switch (op) {
6216   case MAT_NO_OFF_PROC_ENTRIES:
6217     *flg = mat->nooffprocentries;
6218     break;
6219   case MAT_NO_OFF_PROC_ZERO_ROWS:
6220     *flg = mat->nooffproczerorows;
6221     break;
6222   case MAT_SYMMETRIC:
6223     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6224     break;
6225   case MAT_HERMITIAN:
6226     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6227     break;
6228   case MAT_STRUCTURALLY_SYMMETRIC:
6229     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6230     break;
6231   case MAT_SPD:
6232     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6233     break;
6234   case MAT_SYMMETRY_ETERNAL:
6235     *flg = mat->symmetry_eternal;
6236     break;
6237   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6238     *flg = mat->symmetry_eternal;
6239     break;
6240   default:
6241     break;
6242   }
6243   PetscFunctionReturn(PETSC_SUCCESS);
6244 }
6245 
6246 /*@
6247   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6248   this routine retains the old nonzero structure.
6249 
6250   Logically Collective
6251 
6252   Input Parameter:
6253 . mat - the matrix
6254 
6255   Level: intermediate
6256 
6257   Note:
6258   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.
6259   See the Performance chapter of the users manual for information on preallocating matrices.
6260 
6261 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6262 @*/
6263 PetscErrorCode MatZeroEntries(Mat mat)
6264 {
6265   PetscFunctionBegin;
6266   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6267   PetscValidType(mat, 1);
6268   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6269   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");
6270   MatCheckPreallocated(mat, 1);
6271 
6272   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6273   PetscUseTypeMethod(mat, zeroentries);
6274   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6275   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6276   PetscFunctionReturn(PETSC_SUCCESS);
6277 }
6278 
6279 /*@
6280   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6281   of a set of rows and columns of a matrix.
6282 
6283   Collective
6284 
6285   Input Parameters:
6286 + mat     - the matrix
6287 . numRows - the number of rows/columns to zero
6288 . rows    - the global row indices
6289 . diag    - value put in the diagonal of the eliminated rows
6290 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6291 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6292 
6293   Level: intermediate
6294 
6295   Notes:
6296   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6297 
6298   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6299   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
6300 
6301   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6302   Krylov method to take advantage of the known solution on the zeroed rows.
6303 
6304   For the parallel case, all processes that share the matrix (i.e.,
6305   those in the communicator used for matrix creation) MUST call this
6306   routine, regardless of whether any rows being zeroed are owned by
6307   them.
6308 
6309   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6310   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
6311   missing.
6312 
6313   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6314   list only rows local to itself).
6315 
6316   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6317 
6318 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6319           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6320 @*/
6321 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6322 {
6323   PetscFunctionBegin;
6324   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6325   PetscValidType(mat, 1);
6326   if (numRows) PetscAssertPointer(rows, 3);
6327   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6328   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6329   MatCheckPreallocated(mat, 1);
6330 
6331   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6332   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6333   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6334   PetscFunctionReturn(PETSC_SUCCESS);
6335 }
6336 
6337 /*@
6338   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6339   of a set of rows and columns of a matrix.
6340 
6341   Collective
6342 
6343   Input Parameters:
6344 + mat  - the matrix
6345 . is   - the rows to zero
6346 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6347 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6348 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6349 
6350   Level: intermediate
6351 
6352   Note:
6353   See `MatZeroRowsColumns()` for details on how this routine operates.
6354 
6355 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6356           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6357 @*/
6358 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6359 {
6360   PetscInt        numRows;
6361   const PetscInt *rows;
6362 
6363   PetscFunctionBegin;
6364   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6365   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6366   PetscValidType(mat, 1);
6367   PetscValidType(is, 2);
6368   PetscCall(ISGetLocalSize(is, &numRows));
6369   PetscCall(ISGetIndices(is, &rows));
6370   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6371   PetscCall(ISRestoreIndices(is, &rows));
6372   PetscFunctionReturn(PETSC_SUCCESS);
6373 }
6374 
6375 /*@
6376   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6377   of a set of rows of a matrix.
6378 
6379   Collective
6380 
6381   Input Parameters:
6382 + mat     - the matrix
6383 . numRows - the number of rows to zero
6384 . rows    - the global row indices
6385 . diag    - value put in the diagonal of the zeroed rows
6386 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6387 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6388 
6389   Level: intermediate
6390 
6391   Notes:
6392   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6393 
6394   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6395 
6396   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6397   Krylov method to take advantage of the known solution on the zeroed rows.
6398 
6399   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)
6400   from the matrix.
6401 
6402   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6403   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6404   formats this does not alter the nonzero structure.
6405 
6406   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6407   of the matrix is not changed the values are
6408   merely zeroed.
6409 
6410   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6411   formats can optionally remove the main diagonal entry from the
6412   nonzero structure as well, by passing 0.0 as the final argument).
6413 
6414   For the parallel case, all processes that share the matrix (i.e.,
6415   those in the communicator used for matrix creation) MUST call this
6416   routine, regardless of whether any rows being zeroed are owned by
6417   them.
6418 
6419   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6420   list only rows local to itself).
6421 
6422   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6423   owns that are to be zeroed. This saves a global synchronization in the implementation.
6424 
6425 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6426           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6427 @*/
6428 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6429 {
6430   PetscFunctionBegin;
6431   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6432   PetscValidType(mat, 1);
6433   if (numRows) PetscAssertPointer(rows, 3);
6434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6436   MatCheckPreallocated(mat, 1);
6437 
6438   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6439   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6440   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6441   PetscFunctionReturn(PETSC_SUCCESS);
6442 }
6443 
6444 /*@
6445   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6446   of a set of rows of a matrix indicated by an `IS`
6447 
6448   Collective
6449 
6450   Input Parameters:
6451 + mat  - the matrix
6452 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6453 . diag - value put in all diagonals of eliminated rows
6454 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6455 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6456 
6457   Level: intermediate
6458 
6459   Note:
6460   See `MatZeroRows()` for details on how this routine operates.
6461 
6462 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6463           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6464 @*/
6465 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6466 {
6467   PetscInt        numRows = 0;
6468   const PetscInt *rows    = NULL;
6469 
6470   PetscFunctionBegin;
6471   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6472   PetscValidType(mat, 1);
6473   if (is) {
6474     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6475     PetscCall(ISGetLocalSize(is, &numRows));
6476     PetscCall(ISGetIndices(is, &rows));
6477   }
6478   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6479   if (is) PetscCall(ISRestoreIndices(is, &rows));
6480   PetscFunctionReturn(PETSC_SUCCESS);
6481 }
6482 
6483 /*@
6484   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6485   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6486 
6487   Collective
6488 
6489   Input Parameters:
6490 + mat     - the matrix
6491 . numRows - the number of rows to remove
6492 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6493 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6494 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6495 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6496 
6497   Level: intermediate
6498 
6499   Notes:
6500   See `MatZeroRows()` for details on how this routine operates.
6501 
6502   The grid coordinates are across the entire grid, not just the local portion
6503 
6504   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6505   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6506   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6507   `DM_BOUNDARY_PERIODIC` boundary type.
6508 
6509   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
6510   a single value per point) you can skip filling those indices.
6511 
6512   Fortran Note:
6513   `idxm` and `idxn` should be declared as
6514 $     MatStencil idxm(4, m)
6515   and the values inserted using
6516 .vb
6517     idxm(MatStencil_i, 1) = i
6518     idxm(MatStencil_j, 1) = j
6519     idxm(MatStencil_k, 1) = k
6520     idxm(MatStencil_c, 1) = c
6521    etc
6522 .ve
6523 
6524 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6525           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6526 @*/
6527 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6528 {
6529   PetscInt  dim    = mat->stencil.dim;
6530   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6531   PetscInt *dims   = mat->stencil.dims + 1;
6532   PetscInt *starts = mat->stencil.starts;
6533   PetscInt *dxm    = (PetscInt *)rows;
6534   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6535 
6536   PetscFunctionBegin;
6537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6538   PetscValidType(mat, 1);
6539   if (numRows) PetscAssertPointer(rows, 3);
6540 
6541   PetscCall(PetscMalloc1(numRows, &jdxm));
6542   for (i = 0; i < numRows; ++i) {
6543     /* Skip unused dimensions (they are ordered k, j, i, c) */
6544     for (j = 0; j < 3 - sdim; ++j) dxm++;
6545     /* Local index in X dir */
6546     tmp = *dxm++ - starts[0];
6547     /* Loop over remaining dimensions */
6548     for (j = 0; j < dim - 1; ++j) {
6549       /* If nonlocal, set index to be negative */
6550       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6551       /* Update local index */
6552       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6553     }
6554     /* Skip component slot if necessary */
6555     if (mat->stencil.noc) dxm++;
6556     /* Local row number */
6557     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6558   }
6559   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6560   PetscCall(PetscFree(jdxm));
6561   PetscFunctionReturn(PETSC_SUCCESS);
6562 }
6563 
6564 /*@
6565   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6566   of a set of rows and columns of a matrix.
6567 
6568   Collective
6569 
6570   Input Parameters:
6571 + mat     - the matrix
6572 . numRows - the number of rows/columns to remove
6573 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6574 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6575 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6576 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6577 
6578   Level: intermediate
6579 
6580   Notes:
6581   See `MatZeroRowsColumns()` for details on how this routine operates.
6582 
6583   The grid coordinates are across the entire grid, not just the local portion
6584 
6585   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6586   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6587   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6588   `DM_BOUNDARY_PERIODIC` boundary type.
6589 
6590   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
6591   a single value per point) you can skip filling those indices.
6592 
6593   Fortran Note:
6594   `idxm` and `idxn` should be declared as
6595 $     MatStencil idxm(4, m)
6596   and the values inserted using
6597 .vb
6598     idxm(MatStencil_i, 1) = i
6599     idxm(MatStencil_j, 1) = j
6600     idxm(MatStencil_k, 1) = k
6601     idxm(MatStencil_c, 1) = c
6602     etc
6603 .ve
6604 
6605 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6606           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6607 @*/
6608 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6609 {
6610   PetscInt  dim    = mat->stencil.dim;
6611   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6612   PetscInt *dims   = mat->stencil.dims + 1;
6613   PetscInt *starts = mat->stencil.starts;
6614   PetscInt *dxm    = (PetscInt *)rows;
6615   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6616 
6617   PetscFunctionBegin;
6618   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6619   PetscValidType(mat, 1);
6620   if (numRows) PetscAssertPointer(rows, 3);
6621 
6622   PetscCall(PetscMalloc1(numRows, &jdxm));
6623   for (i = 0; i < numRows; ++i) {
6624     /* Skip unused dimensions (they are ordered k, j, i, c) */
6625     for (j = 0; j < 3 - sdim; ++j) dxm++;
6626     /* Local index in X dir */
6627     tmp = *dxm++ - starts[0];
6628     /* Loop over remaining dimensions */
6629     for (j = 0; j < dim - 1; ++j) {
6630       /* If nonlocal, set index to be negative */
6631       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6632       /* Update local index */
6633       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6634     }
6635     /* Skip component slot if necessary */
6636     if (mat->stencil.noc) dxm++;
6637     /* Local row number */
6638     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6639   }
6640   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6641   PetscCall(PetscFree(jdxm));
6642   PetscFunctionReturn(PETSC_SUCCESS);
6643 }
6644 
6645 /*@
6646   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6647   of a set of rows of a matrix; using local numbering of rows.
6648 
6649   Collective
6650 
6651   Input Parameters:
6652 + mat     - the matrix
6653 . numRows - the number of rows to remove
6654 . rows    - the local row indices
6655 . diag    - value put in all diagonals of eliminated rows
6656 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6657 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6658 
6659   Level: intermediate
6660 
6661   Notes:
6662   Before calling `MatZeroRowsLocal()`, the user must first set the
6663   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6664 
6665   See `MatZeroRows()` for details on how this routine operates.
6666 
6667 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6668           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6669 @*/
6670 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6671 {
6672   PetscFunctionBegin;
6673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6674   PetscValidType(mat, 1);
6675   if (numRows) PetscAssertPointer(rows, 3);
6676   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6677   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6678   MatCheckPreallocated(mat, 1);
6679 
6680   if (mat->ops->zerorowslocal) {
6681     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6682   } else {
6683     IS              is, newis;
6684     const PetscInt *newRows;
6685 
6686     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6687     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6688     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6689     PetscCall(ISGetIndices(newis, &newRows));
6690     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6691     PetscCall(ISRestoreIndices(newis, &newRows));
6692     PetscCall(ISDestroy(&newis));
6693     PetscCall(ISDestroy(&is));
6694   }
6695   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6696   PetscFunctionReturn(PETSC_SUCCESS);
6697 }
6698 
6699 /*@
6700   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6701   of a set of rows of a matrix; using local numbering of rows.
6702 
6703   Collective
6704 
6705   Input Parameters:
6706 + mat  - the matrix
6707 . is   - index set of rows to remove
6708 . diag - value put in all diagonals of eliminated rows
6709 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6710 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6711 
6712   Level: intermediate
6713 
6714   Notes:
6715   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6716   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6717 
6718   See `MatZeroRows()` for details on how this routine operates.
6719 
6720 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6721           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6722 @*/
6723 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6724 {
6725   PetscInt        numRows;
6726   const PetscInt *rows;
6727 
6728   PetscFunctionBegin;
6729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6730   PetscValidType(mat, 1);
6731   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6732   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6733   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6734   MatCheckPreallocated(mat, 1);
6735 
6736   PetscCall(ISGetLocalSize(is, &numRows));
6737   PetscCall(ISGetIndices(is, &rows));
6738   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6739   PetscCall(ISRestoreIndices(is, &rows));
6740   PetscFunctionReturn(PETSC_SUCCESS);
6741 }
6742 
6743 /*@
6744   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6745   of a set of rows and columns of a matrix; using local numbering of rows.
6746 
6747   Collective
6748 
6749   Input Parameters:
6750 + mat     - the matrix
6751 . numRows - the number of rows to remove
6752 . rows    - the global row indices
6753 . diag    - value put in all diagonals of eliminated rows
6754 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6755 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6756 
6757   Level: intermediate
6758 
6759   Notes:
6760   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6761   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6762 
6763   See `MatZeroRowsColumns()` for details on how this routine operates.
6764 
6765 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6766           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6767 @*/
6768 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6769 {
6770   IS              is, newis;
6771   const PetscInt *newRows;
6772 
6773   PetscFunctionBegin;
6774   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6775   PetscValidType(mat, 1);
6776   if (numRows) PetscAssertPointer(rows, 3);
6777   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6778   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6779   MatCheckPreallocated(mat, 1);
6780 
6781   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6782   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6783   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6784   PetscCall(ISGetIndices(newis, &newRows));
6785   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6786   PetscCall(ISRestoreIndices(newis, &newRows));
6787   PetscCall(ISDestroy(&newis));
6788   PetscCall(ISDestroy(&is));
6789   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6790   PetscFunctionReturn(PETSC_SUCCESS);
6791 }
6792 
6793 /*@
6794   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6795   of a set of rows and columns of a matrix; using local numbering of rows.
6796 
6797   Collective
6798 
6799   Input Parameters:
6800 + mat  - the matrix
6801 . is   - index set of rows to remove
6802 . diag - value put in all diagonals of eliminated rows
6803 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6804 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6805 
6806   Level: intermediate
6807 
6808   Notes:
6809   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6810   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6811 
6812   See `MatZeroRowsColumns()` for details on how this routine operates.
6813 
6814 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6815           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6816 @*/
6817 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6818 {
6819   PetscInt        numRows;
6820   const PetscInt *rows;
6821 
6822   PetscFunctionBegin;
6823   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6824   PetscValidType(mat, 1);
6825   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6826   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6827   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6828   MatCheckPreallocated(mat, 1);
6829 
6830   PetscCall(ISGetLocalSize(is, &numRows));
6831   PetscCall(ISGetIndices(is, &rows));
6832   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6833   PetscCall(ISRestoreIndices(is, &rows));
6834   PetscFunctionReturn(PETSC_SUCCESS);
6835 }
6836 
6837 /*@
6838   MatGetSize - Returns the numbers of rows and columns in a matrix.
6839 
6840   Not Collective
6841 
6842   Input Parameter:
6843 . mat - the matrix
6844 
6845   Output Parameters:
6846 + m - the number of global rows
6847 - n - the number of global columns
6848 
6849   Level: beginner
6850 
6851   Note:
6852   Both output parameters can be `NULL` on input.
6853 
6854 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6855 @*/
6856 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6857 {
6858   PetscFunctionBegin;
6859   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6860   if (m) *m = mat->rmap->N;
6861   if (n) *n = mat->cmap->N;
6862   PetscFunctionReturn(PETSC_SUCCESS);
6863 }
6864 
6865 /*@
6866   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6867   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6868 
6869   Not Collective
6870 
6871   Input Parameter:
6872 . mat - the matrix
6873 
6874   Output Parameters:
6875 + m - the number of local rows, use `NULL` to not obtain this value
6876 - n - the number of local columns, use `NULL` to not obtain this value
6877 
6878   Level: beginner
6879 
6880 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6881 @*/
6882 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6883 {
6884   PetscFunctionBegin;
6885   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6886   if (m) PetscAssertPointer(m, 2);
6887   if (n) PetscAssertPointer(n, 3);
6888   if (m) *m = mat->rmap->n;
6889   if (n) *n = mat->cmap->n;
6890   PetscFunctionReturn(PETSC_SUCCESS);
6891 }
6892 
6893 /*@
6894   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6895   vector one multiplies this matrix by that are owned by this processor.
6896 
6897   Not Collective, unless matrix has not been allocated, then collective
6898 
6899   Input Parameter:
6900 . mat - the matrix
6901 
6902   Output Parameters:
6903 + m - the global index of the first local column, use `NULL` to not obtain this value
6904 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6905 
6906   Level: developer
6907 
6908   Notes:
6909   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6910 
6911   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6912   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6913 
6914   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6915   the local values in the matrix.
6916 
6917   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6918   Layouts](sec_matlayout) for details on matrix layouts.
6919 
6920 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6921           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6922 @*/
6923 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6924 {
6925   PetscFunctionBegin;
6926   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6927   PetscValidType(mat, 1);
6928   if (m) PetscAssertPointer(m, 2);
6929   if (n) PetscAssertPointer(n, 3);
6930   MatCheckPreallocated(mat, 1);
6931   if (m) *m = mat->cmap->rstart;
6932   if (n) *n = mat->cmap->rend;
6933   PetscFunctionReturn(PETSC_SUCCESS);
6934 }
6935 
6936 /*@
6937   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6938   this MPI process.
6939 
6940   Not Collective
6941 
6942   Input Parameter:
6943 . mat - the matrix
6944 
6945   Output Parameters:
6946 + m - the global index of the first local row, use `NULL` to not obtain this value
6947 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6948 
6949   Level: beginner
6950 
6951   Notes:
6952   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6953 
6954   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6955   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6956 
6957   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6958   the local values in the matrix.
6959 
6960   The high argument is one more than the last element stored locally.
6961 
6962   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6963   would contain the result of a matrix vector product with this matrix. See [Matrix
6964   Layouts](sec_matlayout) for details on matrix layouts.
6965 
6966 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6967           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6968 @*/
6969 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6970 {
6971   PetscFunctionBegin;
6972   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6973   PetscValidType(mat, 1);
6974   if (m) PetscAssertPointer(m, 2);
6975   if (n) PetscAssertPointer(n, 3);
6976   MatCheckPreallocated(mat, 1);
6977   if (m) *m = mat->rmap->rstart;
6978   if (n) *n = mat->rmap->rend;
6979   PetscFunctionReturn(PETSC_SUCCESS);
6980 }
6981 
6982 /*@C
6983   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6984   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6985 
6986   Not Collective, unless matrix has not been allocated
6987 
6988   Input Parameter:
6989 . mat - the matrix
6990 
6991   Output Parameter:
6992 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6993            where `size` is the number of MPI processes used by `mat`
6994 
6995   Level: beginner
6996 
6997   Notes:
6998   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6999 
7000   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7001   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7002 
7003   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7004   the local values in the matrix.
7005 
7006   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
7007   would contain the result of a matrix vector product with this matrix. See [Matrix
7008   Layouts](sec_matlayout) for details on matrix layouts.
7009 
7010 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
7011           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
7012           `DMDAGetGhostCorners()`, `DM`
7013 @*/
7014 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
7015 {
7016   PetscFunctionBegin;
7017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7018   PetscValidType(mat, 1);
7019   MatCheckPreallocated(mat, 1);
7020   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
7021   PetscFunctionReturn(PETSC_SUCCESS);
7022 }
7023 
7024 /*@C
7025   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
7026   vector one multiplies this vector by that are owned by each processor.
7027 
7028   Not Collective, unless matrix has not been allocated
7029 
7030   Input Parameter:
7031 . mat - the matrix
7032 
7033   Output Parameter:
7034 . ranges - start of each processors portion plus one more than the total length at the end
7035 
7036   Level: beginner
7037 
7038   Notes:
7039   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
7040 
7041   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7042   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7043 
7044   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7045   the local values in the matrix.
7046 
7047   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7048   Layouts](sec_matlayout) for details on matrix layouts.
7049 
7050 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7051           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7052           `DMDAGetGhostCorners()`, `DM`
7053 @*/
7054 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7055 {
7056   PetscFunctionBegin;
7057   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7058   PetscValidType(mat, 1);
7059   MatCheckPreallocated(mat, 1);
7060   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7061   PetscFunctionReturn(PETSC_SUCCESS);
7062 }
7063 
7064 /*@
7065   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7066 
7067   Not Collective
7068 
7069   Input Parameter:
7070 . A - matrix
7071 
7072   Output Parameters:
7073 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7074 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7075 
7076   Level: intermediate
7077 
7078   Note:
7079   You should call `ISDestroy()` on the returned `IS`
7080 
7081   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7082   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7083   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7084   details on matrix layouts.
7085 
7086 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7087 @*/
7088 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7089 {
7090   PetscErrorCode (*f)(Mat, IS *, IS *);
7091 
7092   PetscFunctionBegin;
7093   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7094   PetscValidType(A, 1);
7095   MatCheckPreallocated(A, 1);
7096   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7097   if (f) {
7098     PetscCall((*f)(A, rows, cols));
7099   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7100     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7101     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7102   }
7103   PetscFunctionReturn(PETSC_SUCCESS);
7104 }
7105 
7106 /*@
7107   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7108   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7109   to complete the factorization.
7110 
7111   Collective
7112 
7113   Input Parameters:
7114 + fact - the factorized matrix obtained with `MatGetFactor()`
7115 . mat  - the matrix
7116 . row  - row permutation
7117 . col  - column permutation
7118 - info - structure containing
7119 .vb
7120       levels - number of levels of fill.
7121       expected fill - as ratio of original fill.
7122       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7123                 missing diagonal entries)
7124 .ve
7125 
7126   Level: developer
7127 
7128   Notes:
7129   See [Matrix Factorization](sec_matfactor) for additional information.
7130 
7131   Most users should employ the `KSP` interface for linear solvers
7132   instead of working directly with matrix algebra routines such as this.
7133   See, e.g., `KSPCreate()`.
7134 
7135   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7136 
7137   Developer Note:
7138   The Fortran interface is not autogenerated as the
7139   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7140 
7141 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7142           `MatGetOrdering()`, `MatFactorInfo`
7143 @*/
7144 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7145 {
7146   PetscFunctionBegin;
7147   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7148   PetscValidType(mat, 2);
7149   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7150   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7151   PetscAssertPointer(info, 5);
7152   PetscAssertPointer(fact, 1);
7153   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7154   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7155   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7156   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7157   MatCheckPreallocated(mat, 2);
7158 
7159   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7160   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7161   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7162   PetscFunctionReturn(PETSC_SUCCESS);
7163 }
7164 
7165 /*@
7166   MatICCFactorSymbolic - Performs symbolic incomplete
7167   Cholesky factorization for a symmetric matrix.  Use
7168   `MatCholeskyFactorNumeric()` to complete the factorization.
7169 
7170   Collective
7171 
7172   Input Parameters:
7173 + fact - the factorized matrix obtained with `MatGetFactor()`
7174 . mat  - the matrix to be factored
7175 . perm - row and column permutation
7176 - info - structure containing
7177 .vb
7178       levels - number of levels of fill.
7179       expected fill - as ratio of original fill.
7180 .ve
7181 
7182   Level: developer
7183 
7184   Notes:
7185   Most users should employ the `KSP` interface for linear solvers
7186   instead of working directly with matrix algebra routines such as this.
7187   See, e.g., `KSPCreate()`.
7188 
7189   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7190 
7191   Developer Note:
7192   The Fortran interface is not autogenerated as the
7193   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7194 
7195 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7196 @*/
7197 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7198 {
7199   PetscFunctionBegin;
7200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7201   PetscValidType(mat, 2);
7202   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7203   PetscAssertPointer(info, 4);
7204   PetscAssertPointer(fact, 1);
7205   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7206   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7207   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7208   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7209   MatCheckPreallocated(mat, 2);
7210 
7211   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7212   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7213   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7214   PetscFunctionReturn(PETSC_SUCCESS);
7215 }
7216 
7217 /*@C
7218   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7219   points to an array of valid matrices, they may be reused to store the new
7220   submatrices.
7221 
7222   Collective
7223 
7224   Input Parameters:
7225 + mat   - the matrix
7226 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7227 . irow  - index set of rows to extract
7228 . icol  - index set of columns to extract
7229 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7230 
7231   Output Parameter:
7232 . submat - the array of submatrices
7233 
7234   Level: advanced
7235 
7236   Notes:
7237   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7238   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7239   to extract a parallel submatrix.
7240 
7241   Some matrix types place restrictions on the row and column
7242   indices, such as that they be sorted or that they be equal to each other.
7243 
7244   The index sets may not have duplicate entries.
7245 
7246   When extracting submatrices from a parallel matrix, each processor can
7247   form a different submatrix by setting the rows and columns of its
7248   individual index sets according to the local submatrix desired.
7249 
7250   When finished using the submatrices, the user should destroy
7251   them with `MatDestroySubMatrices()`.
7252 
7253   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7254   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7255 
7256   This routine creates the matrices in submat; you should NOT create them before
7257   calling it. It also allocates the array of matrix pointers submat.
7258 
7259   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7260   request one row/column in a block, they must request all rows/columns that are in
7261   that block. For example, if the block size is 2 you cannot request just row 0 and
7262   column 0.
7263 
7264   Fortran Note:
7265   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7266 
7267 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7268 @*/
7269 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7270 {
7271   PetscInt  i;
7272   PetscBool eq;
7273 
7274   PetscFunctionBegin;
7275   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7276   PetscValidType(mat, 1);
7277   if (n) {
7278     PetscAssertPointer(irow, 3);
7279     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7280     PetscAssertPointer(icol, 4);
7281     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7282   }
7283   PetscAssertPointer(submat, 6);
7284   if (n && scall == MAT_REUSE_MATRIX) {
7285     PetscAssertPointer(*submat, 6);
7286     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7287   }
7288   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7289   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7290   MatCheckPreallocated(mat, 1);
7291   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7292   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7293   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7294   for (i = 0; i < n; i++) {
7295     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7296     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7297     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7298 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7299     if (mat->boundtocpu && mat->bindingpropagates) {
7300       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7301       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7302     }
7303 #endif
7304   }
7305   PetscFunctionReturn(PETSC_SUCCESS);
7306 }
7307 
7308 /*@C
7309   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7310 
7311   Collective
7312 
7313   Input Parameters:
7314 + mat   - the matrix
7315 . n     - the number of submatrixes to be extracted
7316 . irow  - index set of rows to extract
7317 . icol  - index set of columns to extract
7318 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7319 
7320   Output Parameter:
7321 . submat - the array of submatrices
7322 
7323   Level: advanced
7324 
7325   Note:
7326   This is used by `PCGASM`
7327 
7328 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7329 @*/
7330 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7331 {
7332   PetscInt  i;
7333   PetscBool eq;
7334 
7335   PetscFunctionBegin;
7336   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7337   PetscValidType(mat, 1);
7338   if (n) {
7339     PetscAssertPointer(irow, 3);
7340     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7341     PetscAssertPointer(icol, 4);
7342     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7343   }
7344   PetscAssertPointer(submat, 6);
7345   if (n && scall == MAT_REUSE_MATRIX) {
7346     PetscAssertPointer(*submat, 6);
7347     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7348   }
7349   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7350   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7351   MatCheckPreallocated(mat, 1);
7352 
7353   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7354   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7355   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7356   for (i = 0; i < n; i++) {
7357     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7358     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7359   }
7360   PetscFunctionReturn(PETSC_SUCCESS);
7361 }
7362 
7363 /*@C
7364   MatDestroyMatrices - Destroys an array of matrices.
7365 
7366   Collective
7367 
7368   Input Parameters:
7369 + n   - the number of local matrices
7370 - mat - the matrices (this is a pointer to the array of matrices)
7371 
7372   Level: advanced
7373 
7374   Notes:
7375   Frees not only the matrices, but also the array that contains the matrices
7376 
7377   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7378 
7379   Fortran Note:
7380   Does not free the `mat` array.
7381 
7382 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7383 @*/
7384 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7385 {
7386   PetscInt i;
7387 
7388   PetscFunctionBegin;
7389   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7390   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7391   PetscAssertPointer(mat, 2);
7392 
7393   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7394 
7395   /* memory is allocated even if n = 0 */
7396   PetscCall(PetscFree(*mat));
7397   PetscFunctionReturn(PETSC_SUCCESS);
7398 }
7399 
7400 /*@C
7401   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7402 
7403   Collective
7404 
7405   Input Parameters:
7406 + n   - the number of local matrices
7407 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7408                        sequence of `MatCreateSubMatrices()`)
7409 
7410   Level: advanced
7411 
7412   Note:
7413   Frees not only the matrices, but also the array that contains the matrices
7414 
7415   Fortran Note:
7416   Does not free the `mat` array.
7417 
7418 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7419 @*/
7420 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7421 {
7422   Mat mat0;
7423 
7424   PetscFunctionBegin;
7425   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7426   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7427   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7428   PetscAssertPointer(mat, 2);
7429 
7430   mat0 = (*mat)[0];
7431   if (mat0 && mat0->ops->destroysubmatrices) {
7432     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7433   } else {
7434     PetscCall(MatDestroyMatrices(n, mat));
7435   }
7436   PetscFunctionReturn(PETSC_SUCCESS);
7437 }
7438 
7439 /*@
7440   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7441 
7442   Collective
7443 
7444   Input Parameter:
7445 . mat - the matrix
7446 
7447   Output Parameter:
7448 . matstruct - the sequential matrix with the nonzero structure of `mat`
7449 
7450   Level: developer
7451 
7452 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7453 @*/
7454 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7455 {
7456   PetscFunctionBegin;
7457   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7458   PetscAssertPointer(matstruct, 2);
7459 
7460   PetscValidType(mat, 1);
7461   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7462   MatCheckPreallocated(mat, 1);
7463 
7464   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7465   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7466   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7467   PetscFunctionReturn(PETSC_SUCCESS);
7468 }
7469 
7470 /*@C
7471   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7472 
7473   Collective
7474 
7475   Input Parameter:
7476 . mat - the matrix
7477 
7478   Level: advanced
7479 
7480   Note:
7481   This is not needed, one can just call `MatDestroy()`
7482 
7483 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7484 @*/
7485 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7486 {
7487   PetscFunctionBegin;
7488   PetscAssertPointer(mat, 1);
7489   PetscCall(MatDestroy(mat));
7490   PetscFunctionReturn(PETSC_SUCCESS);
7491 }
7492 
7493 /*@
7494   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7495   replaces the index sets by larger ones that represent submatrices with
7496   additional overlap.
7497 
7498   Collective
7499 
7500   Input Parameters:
7501 + mat - the matrix
7502 . n   - the number of index sets
7503 . is  - the array of index sets (these index sets will changed during the call)
7504 - ov  - the additional overlap requested
7505 
7506   Options Database Key:
7507 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7508 
7509   Level: developer
7510 
7511   Note:
7512   The computed overlap preserves the matrix block sizes when the blocks are square.
7513   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7514   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7515 
7516 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7517 @*/
7518 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7519 {
7520   PetscInt i, bs, cbs;
7521 
7522   PetscFunctionBegin;
7523   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7524   PetscValidType(mat, 1);
7525   PetscValidLogicalCollectiveInt(mat, n, 2);
7526   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7527   if (n) {
7528     PetscAssertPointer(is, 3);
7529     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7530   }
7531   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7532   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7533   MatCheckPreallocated(mat, 1);
7534 
7535   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7536   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7537   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7538   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7539   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7540   if (bs == cbs) {
7541     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7542   }
7543   PetscFunctionReturn(PETSC_SUCCESS);
7544 }
7545 
7546 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7547 
7548 /*@
7549   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7550   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7551   additional overlap.
7552 
7553   Collective
7554 
7555   Input Parameters:
7556 + mat - the matrix
7557 . n   - the number of index sets
7558 . is  - the array of index sets (these index sets will changed during the call)
7559 - ov  - the additional overlap requested
7560 
7561   `   Options Database Key:
7562 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7563 
7564   Level: developer
7565 
7566 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7567 @*/
7568 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7569 {
7570   PetscInt i;
7571 
7572   PetscFunctionBegin;
7573   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7574   PetscValidType(mat, 1);
7575   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7576   if (n) {
7577     PetscAssertPointer(is, 3);
7578     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7579   }
7580   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7581   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7582   MatCheckPreallocated(mat, 1);
7583   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7584   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7585   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7586   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7587   PetscFunctionReturn(PETSC_SUCCESS);
7588 }
7589 
7590 /*@
7591   MatGetBlockSize - Returns the matrix block size.
7592 
7593   Not Collective
7594 
7595   Input Parameter:
7596 . mat - the matrix
7597 
7598   Output Parameter:
7599 . bs - block size
7600 
7601   Level: intermediate
7602 
7603   Notes:
7604   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7605 
7606   If the block size has not been set yet this routine returns 1.
7607 
7608 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7609 @*/
7610 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7611 {
7612   PetscFunctionBegin;
7613   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7614   PetscAssertPointer(bs, 2);
7615   *bs = PetscAbs(mat->rmap->bs);
7616   PetscFunctionReturn(PETSC_SUCCESS);
7617 }
7618 
7619 /*@
7620   MatGetBlockSizes - Returns the matrix block row and column sizes.
7621 
7622   Not Collective
7623 
7624   Input Parameter:
7625 . mat - the matrix
7626 
7627   Output Parameters:
7628 + rbs - row block size
7629 - cbs - column block size
7630 
7631   Level: intermediate
7632 
7633   Notes:
7634   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7635   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7636 
7637   If a block size has not been set yet this routine returns 1.
7638 
7639 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7640 @*/
7641 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7642 {
7643   PetscFunctionBegin;
7644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7645   if (rbs) PetscAssertPointer(rbs, 2);
7646   if (cbs) PetscAssertPointer(cbs, 3);
7647   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7648   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7649   PetscFunctionReturn(PETSC_SUCCESS);
7650 }
7651 
7652 /*@
7653   MatSetBlockSize - Sets the matrix block size.
7654 
7655   Logically Collective
7656 
7657   Input Parameters:
7658 + mat - the matrix
7659 - bs  - block size
7660 
7661   Level: intermediate
7662 
7663   Notes:
7664   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7665   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7666 
7667   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7668   is compatible with the matrix local sizes.
7669 
7670 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7671 @*/
7672 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7673 {
7674   PetscFunctionBegin;
7675   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7676   PetscValidLogicalCollectiveInt(mat, bs, 2);
7677   PetscCall(MatSetBlockSizes(mat, bs, bs));
7678   PetscFunctionReturn(PETSC_SUCCESS);
7679 }
7680 
7681 typedef struct {
7682   PetscInt         n;
7683   IS              *is;
7684   Mat             *mat;
7685   PetscObjectState nonzerostate;
7686   Mat              C;
7687 } EnvelopeData;
7688 
7689 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7690 {
7691   EnvelopeData *edata = (EnvelopeData *)*ptr;
7692 
7693   PetscFunctionBegin;
7694   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7695   PetscCall(PetscFree(edata->is));
7696   PetscCall(PetscFree(edata));
7697   PetscFunctionReturn(PETSC_SUCCESS);
7698 }
7699 
7700 /*@
7701   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7702   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7703 
7704   Collective
7705 
7706   Input Parameter:
7707 . mat - the matrix
7708 
7709   Level: intermediate
7710 
7711   Notes:
7712   There can be zeros within the blocks
7713 
7714   The blocks can overlap between processes, including laying on more than two processes
7715 
7716 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7717 @*/
7718 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7719 {
7720   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7721   PetscInt          *diag, *odiag, sc;
7722   VecScatter         scatter;
7723   PetscScalar       *seqv;
7724   const PetscScalar *parv;
7725   const PetscInt    *ia, *ja;
7726   PetscBool          set, flag, done;
7727   Mat                AA = mat, A;
7728   MPI_Comm           comm;
7729   PetscMPIInt        rank, size, tag;
7730   MPI_Status         status;
7731   PetscContainer     container;
7732   EnvelopeData      *edata;
7733   Vec                seq, par;
7734   IS                 isglobal;
7735 
7736   PetscFunctionBegin;
7737   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7738   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7739   if (!set || !flag) {
7740     /* TODO: only needs nonzero structure of transpose */
7741     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7742     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7743   }
7744   PetscCall(MatAIJGetLocalMat(AA, &A));
7745   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7746   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7747 
7748   PetscCall(MatGetLocalSize(mat, &n, NULL));
7749   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7750   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7751   PetscCallMPI(MPI_Comm_size(comm, &size));
7752   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7753 
7754   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7755 
7756   if (rank > 0) {
7757     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7758     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7759   }
7760   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7761   for (i = 0; i < n; i++) {
7762     env = PetscMax(env, ja[ia[i + 1] - 1]);
7763     II  = rstart + i;
7764     if (env == II) {
7765       starts[lblocks]  = tbs;
7766       sizes[lblocks++] = 1 + II - tbs;
7767       tbs              = 1 + II;
7768     }
7769   }
7770   if (rank < size - 1) {
7771     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7772     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7773   }
7774 
7775   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7776   if (!set || !flag) PetscCall(MatDestroy(&AA));
7777   PetscCall(MatDestroy(&A));
7778 
7779   PetscCall(PetscNew(&edata));
7780   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7781   edata->n = lblocks;
7782   /* create IS needed for extracting blocks from the original matrix */
7783   PetscCall(PetscMalloc1(lblocks, &edata->is));
7784   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7785 
7786   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7787   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7788   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7789   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7790   PetscCall(MatSetType(edata->C, MATAIJ));
7791 
7792   /* Communicate the start and end of each row, from each block to the correct rank */
7793   /* TODO: Use PetscSF instead of VecScatter */
7794   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7795   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7796   PetscCall(VecGetArrayWrite(seq, &seqv));
7797   for (PetscInt i = 0; i < lblocks; i++) {
7798     for (PetscInt j = 0; j < sizes[i]; j++) {
7799       seqv[cnt]     = starts[i];
7800       seqv[cnt + 1] = starts[i] + sizes[i];
7801       cnt += 2;
7802     }
7803   }
7804   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7805   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7806   sc -= cnt;
7807   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7808   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7809   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7810   PetscCall(ISDestroy(&isglobal));
7811   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7812   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7813   PetscCall(VecScatterDestroy(&scatter));
7814   PetscCall(VecDestroy(&seq));
7815   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7816   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7817   PetscCall(VecGetArrayRead(par, &parv));
7818   cnt = 0;
7819   PetscCall(MatGetSize(mat, NULL, &n));
7820   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7821     PetscInt start, end, d = 0, od = 0;
7822 
7823     start = (PetscInt)PetscRealPart(parv[cnt]);
7824     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7825     cnt += 2;
7826 
7827     if (start < cstart) {
7828       od += cstart - start + n - cend;
7829       d += cend - cstart;
7830     } else if (start < cend) {
7831       od += n - cend;
7832       d += cend - start;
7833     } else od += n - start;
7834     if (end <= cstart) {
7835       od -= cstart - end + n - cend;
7836       d -= cend - cstart;
7837     } else if (end < cend) {
7838       od -= n - cend;
7839       d -= cend - end;
7840     } else od -= n - end;
7841 
7842     odiag[i] = od;
7843     diag[i]  = d;
7844   }
7845   PetscCall(VecRestoreArrayRead(par, &parv));
7846   PetscCall(VecDestroy(&par));
7847   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7848   PetscCall(PetscFree2(diag, odiag));
7849   PetscCall(PetscFree2(sizes, starts));
7850 
7851   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7852   PetscCall(PetscContainerSetPointer(container, edata));
7853   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7854   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7855   PetscCall(PetscObjectDereference((PetscObject)container));
7856   PetscFunctionReturn(PETSC_SUCCESS);
7857 }
7858 
7859 /*@
7860   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7861 
7862   Collective
7863 
7864   Input Parameters:
7865 + A     - the matrix
7866 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7867 
7868   Output Parameter:
7869 . C - matrix with inverted block diagonal of `A`
7870 
7871   Level: advanced
7872 
7873   Note:
7874   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7875 
7876 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7877 @*/
7878 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7879 {
7880   PetscContainer   container;
7881   EnvelopeData    *edata;
7882   PetscObjectState nonzerostate;
7883 
7884   PetscFunctionBegin;
7885   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7886   if (!container) {
7887     PetscCall(MatComputeVariableBlockEnvelope(A));
7888     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7889   }
7890   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7891   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7892   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7893   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7894 
7895   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7896   *C = edata->C;
7897 
7898   for (PetscInt i = 0; i < edata->n; i++) {
7899     Mat          D;
7900     PetscScalar *dvalues;
7901 
7902     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7903     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7904     PetscCall(MatSeqDenseInvert(D));
7905     PetscCall(MatDenseGetArray(D, &dvalues));
7906     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7907     PetscCall(MatDestroy(&D));
7908   }
7909   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7910   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7911   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7912   PetscFunctionReturn(PETSC_SUCCESS);
7913 }
7914 
7915 /*@
7916   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7917 
7918   Not Collective
7919 
7920   Input Parameters:
7921 + mat     - the matrix
7922 . nblocks - the number of blocks on this process, each block can only exist on a single process
7923 - bsizes  - the block sizes
7924 
7925   Level: intermediate
7926 
7927   Notes:
7928   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7929 
7930   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.
7931 
7932 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7933           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7934 @*/
7935 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7936 {
7937   PetscInt ncnt = 0, nlocal;
7938 
7939   PetscFunctionBegin;
7940   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7941   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7942   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);
7943   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7944   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);
7945   PetscCall(PetscFree(mat->bsizes));
7946   mat->nblocks = nblocks;
7947   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7948   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7949   PetscFunctionReturn(PETSC_SUCCESS);
7950 }
7951 
7952 /*@C
7953   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7954 
7955   Not Collective; No Fortran Support
7956 
7957   Input Parameter:
7958 . mat - the matrix
7959 
7960   Output Parameters:
7961 + nblocks - the number of blocks on this process
7962 - bsizes  - the block sizes
7963 
7964   Level: intermediate
7965 
7966 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7967 @*/
7968 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7969 {
7970   PetscFunctionBegin;
7971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7972   if (nblocks) *nblocks = mat->nblocks;
7973   if (bsizes) *bsizes = mat->bsizes;
7974   PetscFunctionReturn(PETSC_SUCCESS);
7975 }
7976 
7977 /*@
7978   MatSetBlockSizes - Sets the matrix block row and column sizes.
7979 
7980   Logically Collective
7981 
7982   Input Parameters:
7983 + mat - the matrix
7984 . rbs - row block size
7985 - cbs - column block size
7986 
7987   Level: intermediate
7988 
7989   Notes:
7990   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7991   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7992   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7993 
7994   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7995   are compatible with the matrix local sizes.
7996 
7997   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7998 
7999 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
8000 @*/
8001 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
8002 {
8003   PetscFunctionBegin;
8004   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8005   PetscValidLogicalCollectiveInt(mat, rbs, 2);
8006   PetscValidLogicalCollectiveInt(mat, cbs, 3);
8007   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
8008   if (mat->rmap->refcnt) {
8009     ISLocalToGlobalMapping l2g  = NULL;
8010     PetscLayout            nmap = NULL;
8011 
8012     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
8013     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
8014     PetscCall(PetscLayoutDestroy(&mat->rmap));
8015     mat->rmap          = nmap;
8016     mat->rmap->mapping = l2g;
8017   }
8018   if (mat->cmap->refcnt) {
8019     ISLocalToGlobalMapping l2g  = NULL;
8020     PetscLayout            nmap = NULL;
8021 
8022     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
8023     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
8024     PetscCall(PetscLayoutDestroy(&mat->cmap));
8025     mat->cmap          = nmap;
8026     mat->cmap->mapping = l2g;
8027   }
8028   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
8029   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
8030   PetscFunctionReturn(PETSC_SUCCESS);
8031 }
8032 
8033 /*@
8034   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
8035 
8036   Logically Collective
8037 
8038   Input Parameters:
8039 + mat     - the matrix
8040 . fromRow - matrix from which to copy row block size
8041 - fromCol - matrix from which to copy column block size (can be same as fromRow)
8042 
8043   Level: developer
8044 
8045 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
8046 @*/
8047 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8048 {
8049   PetscFunctionBegin;
8050   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8051   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8052   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8053   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8054   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8055   PetscFunctionReturn(PETSC_SUCCESS);
8056 }
8057 
8058 /*@
8059   MatResidual - Default routine to calculate the residual r = b - Ax
8060 
8061   Collective
8062 
8063   Input Parameters:
8064 + mat - the matrix
8065 . b   - the right-hand-side
8066 - x   - the approximate solution
8067 
8068   Output Parameter:
8069 . r - location to store the residual
8070 
8071   Level: developer
8072 
8073 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8074 @*/
8075 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8076 {
8077   PetscFunctionBegin;
8078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8079   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8080   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8081   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8082   PetscValidType(mat, 1);
8083   MatCheckPreallocated(mat, 1);
8084   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8085   if (!mat->ops->residual) {
8086     PetscCall(MatMult(mat, x, r));
8087     PetscCall(VecAYPX(r, -1.0, b));
8088   } else {
8089     PetscUseTypeMethod(mat, residual, b, x, r);
8090   }
8091   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8092   PetscFunctionReturn(PETSC_SUCCESS);
8093 }
8094 
8095 /*MC
8096     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8097 
8098     Synopsis:
8099     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8100 
8101     Not Collective
8102 
8103     Input Parameters:
8104 +   A - the matrix
8105 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8106 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8107 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8108                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8109                  always used.
8110 
8111     Output Parameters:
8112 +   n - number of local rows in the (possibly compressed) matrix
8113 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8114 .   ja - the column indices
8115 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8116            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8117 
8118     Level: developer
8119 
8120     Note:
8121     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8122 
8123 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8124 M*/
8125 
8126 /*MC
8127     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8128 
8129     Synopsis:
8130     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8131 
8132     Not Collective
8133 
8134     Input Parameters:
8135 +   A - the  matrix
8136 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8137 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8138     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8139                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8140                  always used.
8141 .   n - number of local rows in the (possibly compressed) matrix
8142 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8143 .   ja - the column indices
8144 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8145            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8146 
8147     Level: developer
8148 
8149 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8150 M*/
8151 
8152 /*@C
8153   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8154 
8155   Collective
8156 
8157   Input Parameters:
8158 + mat             - the matrix
8159 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8160 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8161 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8162                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8163                  always used.
8164 
8165   Output Parameters:
8166 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8167 . 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
8168 . ja   - the column indices, use `NULL` if not needed
8169 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8170            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8171 
8172   Level: developer
8173 
8174   Notes:
8175   You CANNOT change any of the ia[] or ja[] values.
8176 
8177   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8178 
8179   Fortran Notes:
8180   Use
8181 .vb
8182     PetscInt, pointer :: ia(:),ja(:)
8183     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8184     ! Access the ith and jth entries via ia(i) and ja(j)
8185 .ve
8186 
8187   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8188 
8189 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8190 @*/
8191 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8192 {
8193   PetscFunctionBegin;
8194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8195   PetscValidType(mat, 1);
8196   if (n) PetscAssertPointer(n, 5);
8197   if (ia) PetscAssertPointer(ia, 6);
8198   if (ja) PetscAssertPointer(ja, 7);
8199   if (done) PetscAssertPointer(done, 8);
8200   MatCheckPreallocated(mat, 1);
8201   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8202   else {
8203     if (done) *done = PETSC_TRUE;
8204     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8205     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8206     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8207   }
8208   PetscFunctionReturn(PETSC_SUCCESS);
8209 }
8210 
8211 /*@C
8212   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8213 
8214   Collective
8215 
8216   Input Parameters:
8217 + mat             - the matrix
8218 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8219 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8220                 symmetrized
8221 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8222                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8223                  always used.
8224 . n               - number of columns in the (possibly compressed) matrix
8225 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8226 - ja              - the row indices
8227 
8228   Output Parameter:
8229 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8230 
8231   Level: developer
8232 
8233 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8234 @*/
8235 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8236 {
8237   PetscFunctionBegin;
8238   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8239   PetscValidType(mat, 1);
8240   PetscAssertPointer(n, 5);
8241   if (ia) PetscAssertPointer(ia, 6);
8242   if (ja) PetscAssertPointer(ja, 7);
8243   PetscAssertPointer(done, 8);
8244   MatCheckPreallocated(mat, 1);
8245   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8246   else {
8247     *done = PETSC_TRUE;
8248     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8249   }
8250   PetscFunctionReturn(PETSC_SUCCESS);
8251 }
8252 
8253 /*@C
8254   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8255 
8256   Collective
8257 
8258   Input Parameters:
8259 + mat             - the matrix
8260 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8261 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8262 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8263                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8264                     always used.
8265 . n               - size of (possibly compressed) matrix
8266 . ia              - the row pointers
8267 - ja              - the column indices
8268 
8269   Output Parameter:
8270 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8271 
8272   Level: developer
8273 
8274   Note:
8275   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8276   us of the array after it has been restored. If you pass `NULL`, it will
8277   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8278 
8279   Fortran Note:
8280   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8281 
8282 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8283 @*/
8284 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8285 {
8286   PetscFunctionBegin;
8287   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8288   PetscValidType(mat, 1);
8289   if (ia) PetscAssertPointer(ia, 6);
8290   if (ja) PetscAssertPointer(ja, 7);
8291   if (done) PetscAssertPointer(done, 8);
8292   MatCheckPreallocated(mat, 1);
8293 
8294   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8295   else {
8296     if (done) *done = PETSC_TRUE;
8297     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8298     if (n) *n = 0;
8299     if (ia) *ia = NULL;
8300     if (ja) *ja = NULL;
8301   }
8302   PetscFunctionReturn(PETSC_SUCCESS);
8303 }
8304 
8305 /*@C
8306   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8307 
8308   Collective
8309 
8310   Input Parameters:
8311 + mat             - the matrix
8312 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8313 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8314 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8315                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8316                     always used.
8317 
8318   Output Parameters:
8319 + n    - size of (possibly compressed) matrix
8320 . ia   - the column pointers
8321 . ja   - the row indices
8322 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8323 
8324   Level: developer
8325 
8326 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8327 @*/
8328 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8329 {
8330   PetscFunctionBegin;
8331   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8332   PetscValidType(mat, 1);
8333   if (ia) PetscAssertPointer(ia, 6);
8334   if (ja) PetscAssertPointer(ja, 7);
8335   PetscAssertPointer(done, 8);
8336   MatCheckPreallocated(mat, 1);
8337 
8338   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8339   else {
8340     *done = PETSC_TRUE;
8341     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8342     if (n) *n = 0;
8343     if (ia) *ia = NULL;
8344     if (ja) *ja = NULL;
8345   }
8346   PetscFunctionReturn(PETSC_SUCCESS);
8347 }
8348 
8349 /*@
8350   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8351   `MatGetColumnIJ()`.
8352 
8353   Collective
8354 
8355   Input Parameters:
8356 + mat        - the matrix
8357 . ncolors    - maximum color value
8358 . n          - number of entries in colorarray
8359 - colorarray - array indicating color for each column
8360 
8361   Output Parameter:
8362 . iscoloring - coloring generated using colorarray information
8363 
8364   Level: developer
8365 
8366 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8367 @*/
8368 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8369 {
8370   PetscFunctionBegin;
8371   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8372   PetscValidType(mat, 1);
8373   PetscAssertPointer(colorarray, 4);
8374   PetscAssertPointer(iscoloring, 5);
8375   MatCheckPreallocated(mat, 1);
8376 
8377   if (!mat->ops->coloringpatch) {
8378     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8379   } else {
8380     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8381   }
8382   PetscFunctionReturn(PETSC_SUCCESS);
8383 }
8384 
8385 /*@
8386   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8387 
8388   Logically Collective
8389 
8390   Input Parameter:
8391 . mat - the factored matrix to be reset
8392 
8393   Level: developer
8394 
8395   Notes:
8396   This routine should be used only with factored matrices formed by in-place
8397   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8398   format).  This option can save memory, for example, when solving nonlinear
8399   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8400   ILU(0) preconditioner.
8401 
8402   One can specify in-place ILU(0) factorization by calling
8403 .vb
8404      PCType(pc,PCILU);
8405      PCFactorSeUseInPlace(pc);
8406 .ve
8407   or by using the options -pc_type ilu -pc_factor_in_place
8408 
8409   In-place factorization ILU(0) can also be used as a local
8410   solver for the blocks within the block Jacobi or additive Schwarz
8411   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8412   for details on setting local solver options.
8413 
8414   Most users should employ the `KSP` interface for linear solvers
8415   instead of working directly with matrix algebra routines such as this.
8416   See, e.g., `KSPCreate()`.
8417 
8418 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8419 @*/
8420 PetscErrorCode MatSetUnfactored(Mat mat)
8421 {
8422   PetscFunctionBegin;
8423   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8424   PetscValidType(mat, 1);
8425   MatCheckPreallocated(mat, 1);
8426   mat->factortype = MAT_FACTOR_NONE;
8427   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8428   PetscUseTypeMethod(mat, setunfactored);
8429   PetscFunctionReturn(PETSC_SUCCESS);
8430 }
8431 
8432 /*MC
8433     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8434 
8435     Synopsis:
8436     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8437 
8438     Not Collective
8439 
8440     Input Parameter:
8441 .   x - matrix
8442 
8443     Output Parameters:
8444 +   xx_v - the Fortran pointer to the array
8445 -   ierr - error code
8446 
8447     Example of Usage:
8448 .vb
8449       PetscScalar, pointer xx_v(:,:)
8450       ....
8451       call MatDenseGetArrayF90(x,xx_v,ierr)
8452       a = xx_v(3)
8453       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8454 .ve
8455 
8456     Level: advanced
8457 
8458 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8459 M*/
8460 
8461 /*MC
8462     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8463     accessed with `MatDenseGetArrayF90()`.
8464 
8465     Synopsis:
8466     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8467 
8468     Not Collective
8469 
8470     Input Parameters:
8471 +   x - matrix
8472 -   xx_v - the Fortran90 pointer to the array
8473 
8474     Output Parameter:
8475 .   ierr - error code
8476 
8477     Example of Usage:
8478 .vb
8479        PetscScalar, pointer xx_v(:,:)
8480        ....
8481        call MatDenseGetArrayF90(x,xx_v,ierr)
8482        a = xx_v(3)
8483        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8484 .ve
8485 
8486     Level: advanced
8487 
8488 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8489 M*/
8490 
8491 /*MC
8492     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8493 
8494     Synopsis:
8495     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8496 
8497     Not Collective
8498 
8499     Input Parameter:
8500 .   x - matrix
8501 
8502     Output Parameters:
8503 +   xx_v - the Fortran pointer to the array
8504 -   ierr - error code
8505 
8506     Example of Usage:
8507 .vb
8508       PetscScalar, pointer xx_v(:)
8509       ....
8510       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8511       a = xx_v(3)
8512       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8513 .ve
8514 
8515     Level: advanced
8516 
8517 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8518 M*/
8519 
8520 /*MC
8521     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8522     accessed with `MatSeqAIJGetArrayF90()`.
8523 
8524     Synopsis:
8525     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8526 
8527     Not Collective
8528 
8529     Input Parameters:
8530 +   x - matrix
8531 -   xx_v - the Fortran90 pointer to the array
8532 
8533     Output Parameter:
8534 .   ierr - error code
8535 
8536     Example of Usage:
8537 .vb
8538        PetscScalar, pointer xx_v(:)
8539        ....
8540        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8541        a = xx_v(3)
8542        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8543 .ve
8544 
8545     Level: advanced
8546 
8547 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8548 M*/
8549 
8550 /*@
8551   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8552   as the original matrix.
8553 
8554   Collective
8555 
8556   Input Parameters:
8557 + mat   - the original matrix
8558 . isrow - parallel `IS` containing the rows this processor should obtain
8559 . 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.
8560 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8561 
8562   Output Parameter:
8563 . newmat - the new submatrix, of the same type as the original matrix
8564 
8565   Level: advanced
8566 
8567   Notes:
8568   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8569 
8570   Some matrix types place restrictions on the row and column indices, such
8571   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;
8572   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8573 
8574   The index sets may not have duplicate entries.
8575 
8576   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8577   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8578   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8579   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8580   you are finished using it.
8581 
8582   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8583   the input matrix.
8584 
8585   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8586 
8587   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8588   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8589 
8590   Example usage:
8591   Consider the following 8x8 matrix with 34 non-zero values, that is
8592   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8593   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8594   as follows
8595 .vb
8596             1  2  0  |  0  3  0  |  0  4
8597     Proc0   0  5  6  |  7  0  0  |  8  0
8598             9  0 10  | 11  0  0  | 12  0
8599     -------------------------------------
8600            13  0 14  | 15 16 17  |  0  0
8601     Proc1   0 18  0  | 19 20 21  |  0  0
8602             0  0  0  | 22 23  0  | 24  0
8603     -------------------------------------
8604     Proc2  25 26 27  |  0  0 28  | 29  0
8605            30  0  0  | 31 32 33  |  0 34
8606 .ve
8607 
8608   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8609 
8610 .vb
8611             2  0  |  0  3  0  |  0
8612     Proc0   5  6  |  7  0  0  |  8
8613     -------------------------------
8614     Proc1  18  0  | 19 20 21  |  0
8615     -------------------------------
8616     Proc2  26 27  |  0  0 28  | 29
8617             0  0  | 31 32 33  |  0
8618 .ve
8619 
8620 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8621 @*/
8622 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8623 {
8624   PetscMPIInt size;
8625   Mat        *local;
8626   IS          iscoltmp;
8627   PetscBool   flg;
8628 
8629   PetscFunctionBegin;
8630   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8631   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8632   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8633   PetscAssertPointer(newmat, 5);
8634   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8635   PetscValidType(mat, 1);
8636   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8637   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8638 
8639   MatCheckPreallocated(mat, 1);
8640   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8641 
8642   if (!iscol || isrow == iscol) {
8643     PetscBool   stride;
8644     PetscMPIInt grabentirematrix = 0, grab;
8645     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8646     if (stride) {
8647       PetscInt first, step, n, rstart, rend;
8648       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8649       if (step == 1) {
8650         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8651         if (rstart == first) {
8652           PetscCall(ISGetLocalSize(isrow, &n));
8653           if (n == rend - rstart) grabentirematrix = 1;
8654         }
8655       }
8656     }
8657     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8658     if (grab) {
8659       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8660       if (cll == MAT_INITIAL_MATRIX) {
8661         *newmat = mat;
8662         PetscCall(PetscObjectReference((PetscObject)mat));
8663       }
8664       PetscFunctionReturn(PETSC_SUCCESS);
8665     }
8666   }
8667 
8668   if (!iscol) {
8669     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8670   } else {
8671     iscoltmp = iscol;
8672   }
8673 
8674   /* if original matrix is on just one processor then use submatrix generated */
8675   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8676     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8677     goto setproperties;
8678   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8679     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8680     *newmat = *local;
8681     PetscCall(PetscFree(local));
8682     goto setproperties;
8683   } else if (!mat->ops->createsubmatrix) {
8684     /* Create a new matrix type that implements the operation using the full matrix */
8685     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8686     switch (cll) {
8687     case MAT_INITIAL_MATRIX:
8688       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8689       break;
8690     case MAT_REUSE_MATRIX:
8691       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8692       break;
8693     default:
8694       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8695     }
8696     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8697     goto setproperties;
8698   }
8699 
8700   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8701   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8702   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8703 
8704 setproperties:
8705   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8706     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8707     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8708   }
8709   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8710   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8711   PetscFunctionReturn(PETSC_SUCCESS);
8712 }
8713 
8714 /*@
8715   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8716 
8717   Not Collective
8718 
8719   Input Parameters:
8720 + A - the matrix we wish to propagate options from
8721 - B - the matrix we wish to propagate options to
8722 
8723   Level: beginner
8724 
8725   Note:
8726   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8727 
8728 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8729 @*/
8730 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8731 {
8732   PetscFunctionBegin;
8733   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8734   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8735   B->symmetry_eternal            = A->symmetry_eternal;
8736   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8737   B->symmetric                   = A->symmetric;
8738   B->structurally_symmetric      = A->structurally_symmetric;
8739   B->spd                         = A->spd;
8740   B->hermitian                   = A->hermitian;
8741   PetscFunctionReturn(PETSC_SUCCESS);
8742 }
8743 
8744 /*@
8745   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8746   used during the assembly process to store values that belong to
8747   other processors.
8748 
8749   Not Collective
8750 
8751   Input Parameters:
8752 + mat   - the matrix
8753 . size  - the initial size of the stash.
8754 - bsize - the initial size of the block-stash(if used).
8755 
8756   Options Database Keys:
8757 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8758 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8759 
8760   Level: intermediate
8761 
8762   Notes:
8763   The block-stash is used for values set with `MatSetValuesBlocked()` while
8764   the stash is used for values set with `MatSetValues()`
8765 
8766   Run with the option -info and look for output of the form
8767   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8768   to determine the appropriate value, MM, to use for size and
8769   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8770   to determine the value, BMM to use for bsize
8771 
8772 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8773 @*/
8774 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8775 {
8776   PetscFunctionBegin;
8777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8778   PetscValidType(mat, 1);
8779   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8780   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8781   PetscFunctionReturn(PETSC_SUCCESS);
8782 }
8783 
8784 /*@
8785   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8786   the matrix
8787 
8788   Neighbor-wise Collective
8789 
8790   Input Parameters:
8791 + A - the matrix
8792 . x - the vector to be multiplied by the interpolation operator
8793 - y - the vector to be added to the result
8794 
8795   Output Parameter:
8796 . w - the resulting vector
8797 
8798   Level: intermediate
8799 
8800   Notes:
8801   `w` may be the same vector as `y`.
8802 
8803   This allows one to use either the restriction or interpolation (its transpose)
8804   matrix to do the interpolation
8805 
8806 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8807 @*/
8808 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8809 {
8810   PetscInt M, N, Ny;
8811 
8812   PetscFunctionBegin;
8813   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8814   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8815   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8816   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8817   PetscCall(MatGetSize(A, &M, &N));
8818   PetscCall(VecGetSize(y, &Ny));
8819   if (M == Ny) {
8820     PetscCall(MatMultAdd(A, x, y, w));
8821   } else {
8822     PetscCall(MatMultTransposeAdd(A, x, y, w));
8823   }
8824   PetscFunctionReturn(PETSC_SUCCESS);
8825 }
8826 
8827 /*@
8828   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8829   the matrix
8830 
8831   Neighbor-wise Collective
8832 
8833   Input Parameters:
8834 + A - the matrix
8835 - x - the vector to be interpolated
8836 
8837   Output Parameter:
8838 . y - the resulting vector
8839 
8840   Level: intermediate
8841 
8842   Note:
8843   This allows one to use either the restriction or interpolation (its transpose)
8844   matrix to do the interpolation
8845 
8846 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8847 @*/
8848 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8849 {
8850   PetscInt M, N, Ny;
8851 
8852   PetscFunctionBegin;
8853   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8854   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8855   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8856   PetscCall(MatGetSize(A, &M, &N));
8857   PetscCall(VecGetSize(y, &Ny));
8858   if (M == Ny) {
8859     PetscCall(MatMult(A, x, y));
8860   } else {
8861     PetscCall(MatMultTranspose(A, x, y));
8862   }
8863   PetscFunctionReturn(PETSC_SUCCESS);
8864 }
8865 
8866 /*@
8867   MatRestrict - $y = A*x$ or $A^T*x$
8868 
8869   Neighbor-wise Collective
8870 
8871   Input Parameters:
8872 + A - the matrix
8873 - x - the vector to be restricted
8874 
8875   Output Parameter:
8876 . y - the resulting vector
8877 
8878   Level: intermediate
8879 
8880   Note:
8881   This allows one to use either the restriction or interpolation (its transpose)
8882   matrix to do the restriction
8883 
8884 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8885 @*/
8886 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8887 {
8888   PetscInt M, N, Nx;
8889 
8890   PetscFunctionBegin;
8891   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8892   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8893   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8894   PetscCall(MatGetSize(A, &M, &N));
8895   PetscCall(VecGetSize(x, &Nx));
8896   if (M == Nx) {
8897     PetscCall(MatMultTranspose(A, x, y));
8898   } else {
8899     PetscCall(MatMult(A, x, y));
8900   }
8901   PetscFunctionReturn(PETSC_SUCCESS);
8902 }
8903 
8904 /*@
8905   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8906 
8907   Neighbor-wise Collective
8908 
8909   Input Parameters:
8910 + A - the matrix
8911 . x - the input dense matrix to be multiplied
8912 - w - the input dense matrix to be added to the result
8913 
8914   Output Parameter:
8915 . y - the output dense matrix
8916 
8917   Level: intermediate
8918 
8919   Note:
8920   This allows one to use either the restriction or interpolation (its transpose)
8921   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8922   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8923 
8924 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8925 @*/
8926 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8927 {
8928   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8929   PetscBool trans = PETSC_TRUE;
8930   MatReuse  reuse = MAT_INITIAL_MATRIX;
8931 
8932   PetscFunctionBegin;
8933   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8934   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8935   PetscValidType(x, 2);
8936   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8937   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8938   PetscCall(MatGetSize(A, &M, &N));
8939   PetscCall(MatGetSize(x, &Mx, &Nx));
8940   if (N == Mx) trans = PETSC_FALSE;
8941   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);
8942   Mo = trans ? N : M;
8943   if (*y) {
8944     PetscCall(MatGetSize(*y, &My, &Ny));
8945     if (Mo == My && Nx == Ny) {
8946       reuse = MAT_REUSE_MATRIX;
8947     } else {
8948       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);
8949       PetscCall(MatDestroy(y));
8950     }
8951   }
8952 
8953   if (w && *y == w) { /* this is to minimize changes in PCMG */
8954     PetscBool flg;
8955 
8956     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8957     if (w) {
8958       PetscInt My, Ny, Mw, Nw;
8959 
8960       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8961       PetscCall(MatGetSize(*y, &My, &Ny));
8962       PetscCall(MatGetSize(w, &Mw, &Nw));
8963       if (!flg || My != Mw || Ny != Nw) w = NULL;
8964     }
8965     if (!w) {
8966       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8967       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8968       PetscCall(PetscObjectDereference((PetscObject)w));
8969     } else {
8970       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8971     }
8972   }
8973   if (!trans) {
8974     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8975   } else {
8976     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8977   }
8978   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8979   PetscFunctionReturn(PETSC_SUCCESS);
8980 }
8981 
8982 /*@
8983   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8984 
8985   Neighbor-wise Collective
8986 
8987   Input Parameters:
8988 + A - the matrix
8989 - x - the input dense matrix
8990 
8991   Output Parameter:
8992 . y - the output dense matrix
8993 
8994   Level: intermediate
8995 
8996   Note:
8997   This allows one to use either the restriction or interpolation (its transpose)
8998   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8999   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
9000 
9001 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
9002 @*/
9003 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
9004 {
9005   PetscFunctionBegin;
9006   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
9007   PetscFunctionReturn(PETSC_SUCCESS);
9008 }
9009 
9010 /*@
9011   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
9012 
9013   Neighbor-wise Collective
9014 
9015   Input Parameters:
9016 + A - the matrix
9017 - x - the input dense matrix
9018 
9019   Output Parameter:
9020 . y - the output dense matrix
9021 
9022   Level: intermediate
9023 
9024   Note:
9025   This allows one to use either the restriction or interpolation (its transpose)
9026   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
9027   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
9028 
9029 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
9030 @*/
9031 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
9032 {
9033   PetscFunctionBegin;
9034   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
9035   PetscFunctionReturn(PETSC_SUCCESS);
9036 }
9037 
9038 /*@
9039   MatGetNullSpace - retrieves the null space of a matrix.
9040 
9041   Logically Collective
9042 
9043   Input Parameters:
9044 + mat    - the matrix
9045 - nullsp - the null space object
9046 
9047   Level: developer
9048 
9049 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
9050 @*/
9051 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
9052 {
9053   PetscFunctionBegin;
9054   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9055   PetscAssertPointer(nullsp, 2);
9056   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
9057   PetscFunctionReturn(PETSC_SUCCESS);
9058 }
9059 
9060 /*@C
9061   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
9062 
9063   Logically Collective
9064 
9065   Input Parameters:
9066 + n   - the number of matrices
9067 - mat - the array of matrices
9068 
9069   Output Parameters:
9070 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
9071 
9072   Level: developer
9073 
9074   Note:
9075   Call `MatRestoreNullspaces()` to provide these to another array of matrices
9076 
9077 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9078           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
9079 @*/
9080 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9081 {
9082   PetscFunctionBegin;
9083   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9084   PetscAssertPointer(mat, 2);
9085   PetscAssertPointer(nullsp, 3);
9086 
9087   PetscCall(PetscCalloc1(3 * n, nullsp));
9088   for (PetscInt i = 0; i < n; i++) {
9089     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9090     (*nullsp)[i] = mat[i]->nullsp;
9091     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9092     (*nullsp)[n + i] = mat[i]->nearnullsp;
9093     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9094     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9095     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9096   }
9097   PetscFunctionReturn(PETSC_SUCCESS);
9098 }
9099 
9100 /*@C
9101   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9102 
9103   Logically Collective
9104 
9105   Input Parameters:
9106 + n      - the number of matrices
9107 . mat    - the array of matrices
9108 - nullsp - an array of null spaces
9109 
9110   Level: developer
9111 
9112   Note:
9113   Call `MatGetNullSpaces()` to create `nullsp`
9114 
9115 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9116           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9117 @*/
9118 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9119 {
9120   PetscFunctionBegin;
9121   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9122   PetscAssertPointer(mat, 2);
9123   PetscAssertPointer(nullsp, 3);
9124   PetscAssertPointer(*nullsp, 3);
9125 
9126   for (PetscInt i = 0; i < n; i++) {
9127     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9128     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9129     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9130     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9131     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9132     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9133     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9134   }
9135   PetscCall(PetscFree(*nullsp));
9136   PetscFunctionReturn(PETSC_SUCCESS);
9137 }
9138 
9139 /*@
9140   MatSetNullSpace - attaches a null space to a matrix.
9141 
9142   Logically Collective
9143 
9144   Input Parameters:
9145 + mat    - the matrix
9146 - nullsp - the null space object
9147 
9148   Level: advanced
9149 
9150   Notes:
9151   This null space is used by the `KSP` linear solvers to solve singular systems.
9152 
9153   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`
9154 
9155   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
9156   to zero but the linear system will still be solved in a least squares sense.
9157 
9158   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9159   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)$.
9160   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
9161   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
9162   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$).
9163   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9164 
9165   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9166   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9167   routine also automatically calls `MatSetTransposeNullSpace()`.
9168 
9169   The user should call `MatNullSpaceDestroy()`.
9170 
9171 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9172           `KSPSetPCSide()`
9173 @*/
9174 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9175 {
9176   PetscFunctionBegin;
9177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9178   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9179   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9180   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9181   mat->nullsp = nullsp;
9182   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9183   PetscFunctionReturn(PETSC_SUCCESS);
9184 }
9185 
9186 /*@
9187   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9188 
9189   Logically Collective
9190 
9191   Input Parameters:
9192 + mat    - the matrix
9193 - nullsp - the null space object
9194 
9195   Level: developer
9196 
9197 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9198 @*/
9199 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9200 {
9201   PetscFunctionBegin;
9202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9203   PetscValidType(mat, 1);
9204   PetscAssertPointer(nullsp, 2);
9205   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9206   PetscFunctionReturn(PETSC_SUCCESS);
9207 }
9208 
9209 /*@
9210   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9211 
9212   Logically Collective
9213 
9214   Input Parameters:
9215 + mat    - the matrix
9216 - nullsp - the null space object
9217 
9218   Level: advanced
9219 
9220   Notes:
9221   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9222 
9223   See `MatSetNullSpace()`
9224 
9225 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9226 @*/
9227 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9228 {
9229   PetscFunctionBegin;
9230   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9231   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9232   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9233   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9234   mat->transnullsp = nullsp;
9235   PetscFunctionReturn(PETSC_SUCCESS);
9236 }
9237 
9238 /*@
9239   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9240   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9241 
9242   Logically Collective
9243 
9244   Input Parameters:
9245 + mat    - the matrix
9246 - nullsp - the null space object
9247 
9248   Level: advanced
9249 
9250   Notes:
9251   Overwrites any previous near null space that may have been attached
9252 
9253   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9254 
9255 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9256 @*/
9257 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9258 {
9259   PetscFunctionBegin;
9260   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9261   PetscValidType(mat, 1);
9262   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9263   MatCheckPreallocated(mat, 1);
9264   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9265   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9266   mat->nearnullsp = nullsp;
9267   PetscFunctionReturn(PETSC_SUCCESS);
9268 }
9269 
9270 /*@
9271   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9272 
9273   Not Collective
9274 
9275   Input Parameter:
9276 . mat - the matrix
9277 
9278   Output Parameter:
9279 . nullsp - the null space object, `NULL` if not set
9280 
9281   Level: advanced
9282 
9283 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9284 @*/
9285 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9286 {
9287   PetscFunctionBegin;
9288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9289   PetscValidType(mat, 1);
9290   PetscAssertPointer(nullsp, 2);
9291   MatCheckPreallocated(mat, 1);
9292   *nullsp = mat->nearnullsp;
9293   PetscFunctionReturn(PETSC_SUCCESS);
9294 }
9295 
9296 /*@
9297   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9298 
9299   Collective
9300 
9301   Input Parameters:
9302 + mat  - the matrix
9303 . row  - row/column permutation
9304 - info - information on desired factorization process
9305 
9306   Level: developer
9307 
9308   Notes:
9309   Probably really in-place only when level of fill is zero, otherwise allocates
9310   new space to store factored matrix and deletes previous memory.
9311 
9312   Most users should employ the `KSP` interface for linear solvers
9313   instead of working directly with matrix algebra routines such as this.
9314   See, e.g., `KSPCreate()`.
9315 
9316   Developer Note:
9317   The Fortran interface is not autogenerated as the
9318   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9319 
9320 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9321 @*/
9322 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9323 {
9324   PetscFunctionBegin;
9325   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9326   PetscValidType(mat, 1);
9327   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9328   PetscAssertPointer(info, 3);
9329   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9330   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9331   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9332   MatCheckPreallocated(mat, 1);
9333   PetscUseTypeMethod(mat, iccfactor, row, info);
9334   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9335   PetscFunctionReturn(PETSC_SUCCESS);
9336 }
9337 
9338 /*@
9339   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9340   ghosted ones.
9341 
9342   Not Collective
9343 
9344   Input Parameters:
9345 + mat  - the matrix
9346 - diag - the diagonal values, including ghost ones
9347 
9348   Level: developer
9349 
9350   Notes:
9351   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9352 
9353   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9354 
9355 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9356 @*/
9357 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9358 {
9359   PetscMPIInt size;
9360 
9361   PetscFunctionBegin;
9362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9363   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9364   PetscValidType(mat, 1);
9365 
9366   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9367   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9368   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9369   if (size == 1) {
9370     PetscInt n, m;
9371     PetscCall(VecGetSize(diag, &n));
9372     PetscCall(MatGetSize(mat, NULL, &m));
9373     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9374     PetscCall(MatDiagonalScale(mat, NULL, diag));
9375   } else {
9376     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9377   }
9378   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9379   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9380   PetscFunctionReturn(PETSC_SUCCESS);
9381 }
9382 
9383 /*@
9384   MatGetInertia - Gets the inertia from a factored matrix
9385 
9386   Collective
9387 
9388   Input Parameter:
9389 . mat - the matrix
9390 
9391   Output Parameters:
9392 + nneg  - number of negative eigenvalues
9393 . nzero - number of zero eigenvalues
9394 - npos  - number of positive eigenvalues
9395 
9396   Level: advanced
9397 
9398   Note:
9399   Matrix must have been factored by `MatCholeskyFactor()`
9400 
9401 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9402 @*/
9403 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9404 {
9405   PetscFunctionBegin;
9406   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9407   PetscValidType(mat, 1);
9408   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9409   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9410   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9411   PetscFunctionReturn(PETSC_SUCCESS);
9412 }
9413 
9414 /*@C
9415   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9416 
9417   Neighbor-wise Collective
9418 
9419   Input Parameters:
9420 + mat - the factored matrix obtained with `MatGetFactor()`
9421 - b   - the right-hand-side vectors
9422 
9423   Output Parameter:
9424 . x - the result vectors
9425 
9426   Level: developer
9427 
9428   Note:
9429   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9430   call `MatSolves`(A,x,x).
9431 
9432 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9433 @*/
9434 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9435 {
9436   PetscFunctionBegin;
9437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9438   PetscValidType(mat, 1);
9439   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9440   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9441   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9442 
9443   MatCheckPreallocated(mat, 1);
9444   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9445   PetscUseTypeMethod(mat, solves, b, x);
9446   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9447   PetscFunctionReturn(PETSC_SUCCESS);
9448 }
9449 
9450 /*@
9451   MatIsSymmetric - Test whether a matrix is symmetric
9452 
9453   Collective
9454 
9455   Input Parameters:
9456 + A   - the matrix to test
9457 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9458 
9459   Output Parameter:
9460 . flg - the result
9461 
9462   Level: intermediate
9463 
9464   Notes:
9465   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9466 
9467   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9468 
9469   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9470   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9471 
9472 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9473           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9474 @*/
9475 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9476 {
9477   PetscFunctionBegin;
9478   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9479   PetscAssertPointer(flg, 3);
9480   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9481   else {
9482     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9483     else PetscCall(MatIsTranspose(A, A, tol, flg));
9484     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9485   }
9486   PetscFunctionReturn(PETSC_SUCCESS);
9487 }
9488 
9489 /*@
9490   MatIsHermitian - Test whether a matrix is Hermitian
9491 
9492   Collective
9493 
9494   Input Parameters:
9495 + A   - the matrix to test
9496 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9497 
9498   Output Parameter:
9499 . flg - the result
9500 
9501   Level: intermediate
9502 
9503   Notes:
9504   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9505 
9506   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9507 
9508   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9509   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9510 
9511 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9512           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9513 @*/
9514 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9515 {
9516   PetscFunctionBegin;
9517   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9518   PetscAssertPointer(flg, 3);
9519   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9520   else {
9521     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9522     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9523     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9524   }
9525   PetscFunctionReturn(PETSC_SUCCESS);
9526 }
9527 
9528 /*@
9529   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9530 
9531   Not Collective
9532 
9533   Input Parameter:
9534 . A - the matrix to check
9535 
9536   Output Parameters:
9537 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9538 - flg - the result (only valid if set is `PETSC_TRUE`)
9539 
9540   Level: advanced
9541 
9542   Notes:
9543   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9544   if you want it explicitly checked
9545 
9546   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9547   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9548 
9549 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9550 @*/
9551 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9552 {
9553   PetscFunctionBegin;
9554   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9555   PetscAssertPointer(set, 2);
9556   PetscAssertPointer(flg, 3);
9557   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9558     *set = PETSC_TRUE;
9559     *flg = PetscBool3ToBool(A->symmetric);
9560   } else {
9561     *set = PETSC_FALSE;
9562   }
9563   PetscFunctionReturn(PETSC_SUCCESS);
9564 }
9565 
9566 /*@
9567   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9568 
9569   Not Collective
9570 
9571   Input Parameter:
9572 . A - the matrix to check
9573 
9574   Output Parameters:
9575 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9576 - flg - the result (only valid if set is `PETSC_TRUE`)
9577 
9578   Level: advanced
9579 
9580   Notes:
9581   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9582 
9583   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9584   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9585 
9586 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9587 @*/
9588 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9589 {
9590   PetscFunctionBegin;
9591   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9592   PetscAssertPointer(set, 2);
9593   PetscAssertPointer(flg, 3);
9594   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9595     *set = PETSC_TRUE;
9596     *flg = PetscBool3ToBool(A->spd);
9597   } else {
9598     *set = PETSC_FALSE;
9599   }
9600   PetscFunctionReturn(PETSC_SUCCESS);
9601 }
9602 
9603 /*@
9604   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9605 
9606   Not Collective
9607 
9608   Input Parameter:
9609 . A - the matrix to check
9610 
9611   Output Parameters:
9612 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9613 - flg - the result (only valid if set is `PETSC_TRUE`)
9614 
9615   Level: advanced
9616 
9617   Notes:
9618   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9619   if you want it explicitly checked
9620 
9621   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9622   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9623 
9624 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9625 @*/
9626 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9627 {
9628   PetscFunctionBegin;
9629   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9630   PetscAssertPointer(set, 2);
9631   PetscAssertPointer(flg, 3);
9632   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9633     *set = PETSC_TRUE;
9634     *flg = PetscBool3ToBool(A->hermitian);
9635   } else {
9636     *set = PETSC_FALSE;
9637   }
9638   PetscFunctionReturn(PETSC_SUCCESS);
9639 }
9640 
9641 /*@
9642   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9643 
9644   Collective
9645 
9646   Input Parameter:
9647 . A - the matrix to test
9648 
9649   Output Parameter:
9650 . flg - the result
9651 
9652   Level: intermediate
9653 
9654   Notes:
9655   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9656 
9657   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
9658   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9659 
9660 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9661 @*/
9662 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9663 {
9664   PetscFunctionBegin;
9665   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9666   PetscAssertPointer(flg, 2);
9667   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9668     *flg = PetscBool3ToBool(A->structurally_symmetric);
9669   } else {
9670     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9671     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9672   }
9673   PetscFunctionReturn(PETSC_SUCCESS);
9674 }
9675 
9676 /*@
9677   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9678 
9679   Not Collective
9680 
9681   Input Parameter:
9682 . A - the matrix to check
9683 
9684   Output Parameters:
9685 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9686 - flg - the result (only valid if set is PETSC_TRUE)
9687 
9688   Level: advanced
9689 
9690   Notes:
9691   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
9692   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9693 
9694   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9695 
9696 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9697 @*/
9698 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9699 {
9700   PetscFunctionBegin;
9701   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9702   PetscAssertPointer(set, 2);
9703   PetscAssertPointer(flg, 3);
9704   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9705     *set = PETSC_TRUE;
9706     *flg = PetscBool3ToBool(A->structurally_symmetric);
9707   } else {
9708     *set = PETSC_FALSE;
9709   }
9710   PetscFunctionReturn(PETSC_SUCCESS);
9711 }
9712 
9713 /*@
9714   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9715   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9716 
9717   Not Collective
9718 
9719   Input Parameter:
9720 . mat - the matrix
9721 
9722   Output Parameters:
9723 + nstash    - the size of the stash
9724 . reallocs  - the number of additional mallocs incurred.
9725 . bnstash   - the size of the block stash
9726 - breallocs - the number of additional mallocs incurred.in the block stash
9727 
9728   Level: advanced
9729 
9730 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9731 @*/
9732 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9733 {
9734   PetscFunctionBegin;
9735   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9736   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9737   PetscFunctionReturn(PETSC_SUCCESS);
9738 }
9739 
9740 /*@
9741   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9742   parallel layout, `PetscLayout` for rows and columns
9743 
9744   Collective
9745 
9746   Input Parameter:
9747 . mat - the matrix
9748 
9749   Output Parameters:
9750 + right - (optional) vector that the matrix can be multiplied against
9751 - left  - (optional) vector that the matrix vector product can be stored in
9752 
9753   Level: advanced
9754 
9755   Notes:
9756   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()`.
9757 
9758   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9759 
9760 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9761 @*/
9762 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9763 {
9764   PetscFunctionBegin;
9765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9766   PetscValidType(mat, 1);
9767   if (mat->ops->getvecs) {
9768     PetscUseTypeMethod(mat, getvecs, right, left);
9769   } else {
9770     if (right) {
9771       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9772       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9773       PetscCall(VecSetType(*right, mat->defaultvectype));
9774 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9775       if (mat->boundtocpu && mat->bindingpropagates) {
9776         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9777         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9778       }
9779 #endif
9780     }
9781     if (left) {
9782       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9783       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9784       PetscCall(VecSetType(*left, mat->defaultvectype));
9785 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9786       if (mat->boundtocpu && mat->bindingpropagates) {
9787         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9788         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9789       }
9790 #endif
9791     }
9792   }
9793   PetscFunctionReturn(PETSC_SUCCESS);
9794 }
9795 
9796 /*@
9797   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9798   with default values.
9799 
9800   Not Collective
9801 
9802   Input Parameter:
9803 . info - the `MatFactorInfo` data structure
9804 
9805   Level: developer
9806 
9807   Notes:
9808   The solvers are generally used through the `KSP` and `PC` objects, for example
9809   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9810 
9811   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9812 
9813 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9814 @*/
9815 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9816 {
9817   PetscFunctionBegin;
9818   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9819   PetscFunctionReturn(PETSC_SUCCESS);
9820 }
9821 
9822 /*@
9823   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9824 
9825   Collective
9826 
9827   Input Parameters:
9828 + mat - the factored matrix
9829 - is  - the index set defining the Schur indices (0-based)
9830 
9831   Level: advanced
9832 
9833   Notes:
9834   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9835 
9836   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9837 
9838   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9839 
9840 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9841           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9842 @*/
9843 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9844 {
9845   PetscErrorCode (*f)(Mat, IS);
9846 
9847   PetscFunctionBegin;
9848   PetscValidType(mat, 1);
9849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9850   PetscValidType(is, 2);
9851   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9852   PetscCheckSameComm(mat, 1, is, 2);
9853   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9854   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9855   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9856   PetscCall(MatDestroy(&mat->schur));
9857   PetscCall((*f)(mat, is));
9858   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9859   PetscFunctionReturn(PETSC_SUCCESS);
9860 }
9861 
9862 /*@
9863   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9864 
9865   Logically Collective
9866 
9867   Input Parameters:
9868 + F      - the factored matrix obtained by calling `MatGetFactor()`
9869 . S      - location where to return the Schur complement, can be `NULL`
9870 - status - the status of the Schur complement matrix, can be `NULL`
9871 
9872   Level: advanced
9873 
9874   Notes:
9875   You must call `MatFactorSetSchurIS()` before calling this routine.
9876 
9877   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9878 
9879   The routine provides a copy of the Schur matrix stored within the solver data structures.
9880   The caller must destroy the object when it is no longer needed.
9881   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9882 
9883   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)
9884 
9885   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9886 
9887   Developer Note:
9888   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9889   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9890 
9891 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9892 @*/
9893 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9894 {
9895   PetscFunctionBegin;
9896   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9897   if (S) PetscAssertPointer(S, 2);
9898   if (status) PetscAssertPointer(status, 3);
9899   if (S) {
9900     PetscErrorCode (*f)(Mat, Mat *);
9901 
9902     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9903     if (f) {
9904       PetscCall((*f)(F, S));
9905     } else {
9906       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9907     }
9908   }
9909   if (status) *status = F->schur_status;
9910   PetscFunctionReturn(PETSC_SUCCESS);
9911 }
9912 
9913 /*@
9914   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9915 
9916   Logically Collective
9917 
9918   Input Parameters:
9919 + F      - the factored matrix obtained by calling `MatGetFactor()`
9920 . S      - location where to return the Schur complement, can be `NULL`
9921 - status - the status of the Schur complement matrix, can be `NULL`
9922 
9923   Level: advanced
9924 
9925   Notes:
9926   You must call `MatFactorSetSchurIS()` before calling this routine.
9927 
9928   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9929 
9930   The routine returns a the Schur Complement stored within the data structures of the solver.
9931 
9932   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9933 
9934   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9935 
9936   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9937 
9938   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9939 
9940 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9941 @*/
9942 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9943 {
9944   PetscFunctionBegin;
9945   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9946   if (S) {
9947     PetscAssertPointer(S, 2);
9948     *S = F->schur;
9949   }
9950   if (status) {
9951     PetscAssertPointer(status, 3);
9952     *status = F->schur_status;
9953   }
9954   PetscFunctionReturn(PETSC_SUCCESS);
9955 }
9956 
9957 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9958 {
9959   Mat S = F->schur;
9960 
9961   PetscFunctionBegin;
9962   switch (F->schur_status) {
9963   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9964   case MAT_FACTOR_SCHUR_INVERTED:
9965     if (S) {
9966       S->ops->solve             = NULL;
9967       S->ops->matsolve          = NULL;
9968       S->ops->solvetranspose    = NULL;
9969       S->ops->matsolvetranspose = NULL;
9970       S->ops->solveadd          = NULL;
9971       S->ops->solvetransposeadd = NULL;
9972       S->factortype             = MAT_FACTOR_NONE;
9973       PetscCall(PetscFree(S->solvertype));
9974     }
9975   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9976     break;
9977   default:
9978     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9979   }
9980   PetscFunctionReturn(PETSC_SUCCESS);
9981 }
9982 
9983 /*@
9984   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9985 
9986   Logically Collective
9987 
9988   Input Parameters:
9989 + F      - the factored matrix obtained by calling `MatGetFactor()`
9990 . S      - location where the Schur complement is stored
9991 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9992 
9993   Level: advanced
9994 
9995 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9996 @*/
9997 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9998 {
9999   PetscFunctionBegin;
10000   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10001   if (S) {
10002     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
10003     *S = NULL;
10004   }
10005   F->schur_status = status;
10006   PetscCall(MatFactorUpdateSchurStatus_Private(F));
10007   PetscFunctionReturn(PETSC_SUCCESS);
10008 }
10009 
10010 /*@
10011   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
10012 
10013   Logically Collective
10014 
10015   Input Parameters:
10016 + F   - the factored matrix obtained by calling `MatGetFactor()`
10017 . rhs - location where the right-hand side of the Schur complement system is stored
10018 - sol - location where the solution of the Schur complement system has to be returned
10019 
10020   Level: advanced
10021 
10022   Notes:
10023   The sizes of the vectors should match the size of the Schur complement
10024 
10025   Must be called after `MatFactorSetSchurIS()`
10026 
10027 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
10028 @*/
10029 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
10030 {
10031   PetscFunctionBegin;
10032   PetscValidType(F, 1);
10033   PetscValidType(rhs, 2);
10034   PetscValidType(sol, 3);
10035   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10036   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10037   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10038   PetscCheckSameComm(F, 1, rhs, 2);
10039   PetscCheckSameComm(F, 1, sol, 3);
10040   PetscCall(MatFactorFactorizeSchurComplement(F));
10041   switch (F->schur_status) {
10042   case MAT_FACTOR_SCHUR_FACTORED:
10043     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
10044     break;
10045   case MAT_FACTOR_SCHUR_INVERTED:
10046     PetscCall(MatMultTranspose(F->schur, rhs, sol));
10047     break;
10048   default:
10049     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10050   }
10051   PetscFunctionReturn(PETSC_SUCCESS);
10052 }
10053 
10054 /*@
10055   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
10056 
10057   Logically Collective
10058 
10059   Input Parameters:
10060 + F   - the factored matrix obtained by calling `MatGetFactor()`
10061 . rhs - location where the right-hand side of the Schur complement system is stored
10062 - sol - location where the solution of the Schur complement system has to be returned
10063 
10064   Level: advanced
10065 
10066   Notes:
10067   The sizes of the vectors should match the size of the Schur complement
10068 
10069   Must be called after `MatFactorSetSchurIS()`
10070 
10071 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
10072 @*/
10073 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
10074 {
10075   PetscFunctionBegin;
10076   PetscValidType(F, 1);
10077   PetscValidType(rhs, 2);
10078   PetscValidType(sol, 3);
10079   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10080   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10081   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10082   PetscCheckSameComm(F, 1, rhs, 2);
10083   PetscCheckSameComm(F, 1, sol, 3);
10084   PetscCall(MatFactorFactorizeSchurComplement(F));
10085   switch (F->schur_status) {
10086   case MAT_FACTOR_SCHUR_FACTORED:
10087     PetscCall(MatSolve(F->schur, rhs, sol));
10088     break;
10089   case MAT_FACTOR_SCHUR_INVERTED:
10090     PetscCall(MatMult(F->schur, rhs, sol));
10091     break;
10092   default:
10093     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10094   }
10095   PetscFunctionReturn(PETSC_SUCCESS);
10096 }
10097 
10098 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10099 #if PetscDefined(HAVE_CUDA)
10100 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10101 #endif
10102 
10103 /* Schur status updated in the interface */
10104 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10105 {
10106   Mat S = F->schur;
10107 
10108   PetscFunctionBegin;
10109   if (S) {
10110     PetscMPIInt size;
10111     PetscBool   isdense, isdensecuda;
10112 
10113     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10114     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10115     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10116     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10117     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10118     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10119     if (isdense) {
10120       PetscCall(MatSeqDenseInvertFactors_Private(S));
10121     } else if (isdensecuda) {
10122 #if defined(PETSC_HAVE_CUDA)
10123       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10124 #endif
10125     }
10126     // HIP??????????????
10127     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10128   }
10129   PetscFunctionReturn(PETSC_SUCCESS);
10130 }
10131 
10132 /*@
10133   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10134 
10135   Logically Collective
10136 
10137   Input Parameter:
10138 . F - the factored matrix obtained by calling `MatGetFactor()`
10139 
10140   Level: advanced
10141 
10142   Notes:
10143   Must be called after `MatFactorSetSchurIS()`.
10144 
10145   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10146 
10147 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10148 @*/
10149 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10150 {
10151   PetscFunctionBegin;
10152   PetscValidType(F, 1);
10153   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10154   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10155   PetscCall(MatFactorFactorizeSchurComplement(F));
10156   PetscCall(MatFactorInvertSchurComplement_Private(F));
10157   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10158   PetscFunctionReturn(PETSC_SUCCESS);
10159 }
10160 
10161 /*@
10162   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10163 
10164   Logically Collective
10165 
10166   Input Parameter:
10167 . F - the factored matrix obtained by calling `MatGetFactor()`
10168 
10169   Level: advanced
10170 
10171   Note:
10172   Must be called after `MatFactorSetSchurIS()`
10173 
10174 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10175 @*/
10176 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10177 {
10178   MatFactorInfo info;
10179 
10180   PetscFunctionBegin;
10181   PetscValidType(F, 1);
10182   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10183   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10184   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10185   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10186   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10187     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10188   } else {
10189     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10190   }
10191   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10192   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10193   PetscFunctionReturn(PETSC_SUCCESS);
10194 }
10195 
10196 /*@
10197   MatPtAP - Creates the matrix product $C = P^T * A * P$
10198 
10199   Neighbor-wise Collective
10200 
10201   Input Parameters:
10202 + A     - the matrix
10203 . P     - the projection matrix
10204 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10205 - 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
10206           if the result is a dense matrix this is irrelevant
10207 
10208   Output Parameter:
10209 . C - the product matrix
10210 
10211   Level: intermediate
10212 
10213   Notes:
10214   C will be created and must be destroyed by the user with `MatDestroy()`.
10215 
10216   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10217 
10218   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10219 
10220   Developer Note:
10221   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10222 
10223 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10224 @*/
10225 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10226 {
10227   PetscFunctionBegin;
10228   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10229   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10230 
10231   if (scall == MAT_INITIAL_MATRIX) {
10232     PetscCall(MatProductCreate(A, P, NULL, C));
10233     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10234     PetscCall(MatProductSetAlgorithm(*C, "default"));
10235     PetscCall(MatProductSetFill(*C, fill));
10236 
10237     (*C)->product->api_user = PETSC_TRUE;
10238     PetscCall(MatProductSetFromOptions(*C));
10239     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);
10240     PetscCall(MatProductSymbolic(*C));
10241   } else { /* scall == MAT_REUSE_MATRIX */
10242     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10243   }
10244 
10245   PetscCall(MatProductNumeric(*C));
10246   (*C)->symmetric = A->symmetric;
10247   (*C)->spd       = A->spd;
10248   PetscFunctionReturn(PETSC_SUCCESS);
10249 }
10250 
10251 /*@
10252   MatRARt - Creates the matrix product $C = R * A * R^T$
10253 
10254   Neighbor-wise Collective
10255 
10256   Input Parameters:
10257 + A     - the matrix
10258 . R     - the projection matrix
10259 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10260 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10261           if the result is a dense matrix this is irrelevant
10262 
10263   Output Parameter:
10264 . C - the product matrix
10265 
10266   Level: intermediate
10267 
10268   Notes:
10269   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10270 
10271   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10272 
10273   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10274   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10275   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10276   We recommend using `MatPtAP()` when possible.
10277 
10278   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10279 
10280 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10281 @*/
10282 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10283 {
10284   PetscFunctionBegin;
10285   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10286   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10287 
10288   if (scall == MAT_INITIAL_MATRIX) {
10289     PetscCall(MatProductCreate(A, R, NULL, C));
10290     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10291     PetscCall(MatProductSetAlgorithm(*C, "default"));
10292     PetscCall(MatProductSetFill(*C, fill));
10293 
10294     (*C)->product->api_user = PETSC_TRUE;
10295     PetscCall(MatProductSetFromOptions(*C));
10296     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);
10297     PetscCall(MatProductSymbolic(*C));
10298   } else { /* scall == MAT_REUSE_MATRIX */
10299     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10300   }
10301 
10302   PetscCall(MatProductNumeric(*C));
10303   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10304   PetscFunctionReturn(PETSC_SUCCESS);
10305 }
10306 
10307 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10308 {
10309   PetscBool flg = PETSC_TRUE;
10310 
10311   PetscFunctionBegin;
10312   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10313   if (scall == MAT_INITIAL_MATRIX) {
10314     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10315     PetscCall(MatProductCreate(A, B, NULL, C));
10316     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10317     PetscCall(MatProductSetFill(*C, fill));
10318   } else { /* scall == MAT_REUSE_MATRIX */
10319     Mat_Product *product = (*C)->product;
10320 
10321     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10322     if (flg && product && product->type != ptype) {
10323       PetscCall(MatProductClear(*C));
10324       product = NULL;
10325     }
10326     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10327     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10328       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10329       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10330       product        = (*C)->product;
10331       product->fill  = fill;
10332       product->clear = PETSC_TRUE;
10333     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10334       flg = PETSC_FALSE;
10335       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10336     }
10337   }
10338   if (flg) {
10339     (*C)->product->api_user = PETSC_TRUE;
10340     PetscCall(MatProductSetType(*C, ptype));
10341     PetscCall(MatProductSetFromOptions(*C));
10342     PetscCall(MatProductSymbolic(*C));
10343   }
10344   PetscCall(MatProductNumeric(*C));
10345   PetscFunctionReturn(PETSC_SUCCESS);
10346 }
10347 
10348 /*@
10349   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10350 
10351   Neighbor-wise Collective
10352 
10353   Input Parameters:
10354 + A     - the left matrix
10355 . B     - the right matrix
10356 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10357 - 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
10358           if the result is a dense matrix this is irrelevant
10359 
10360   Output Parameter:
10361 . C - the product matrix
10362 
10363   Notes:
10364   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10365 
10366   `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
10367   call to this function with `MAT_INITIAL_MATRIX`.
10368 
10369   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10370 
10371   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`,
10372   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10373 
10374   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10375 
10376   Example of Usage:
10377 .vb
10378      MatProductCreate(A,B,NULL,&C);
10379      MatProductSetType(C,MATPRODUCT_AB);
10380      MatProductSymbolic(C);
10381      MatProductNumeric(C); // compute C=A * B
10382      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10383      MatProductNumeric(C);
10384      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10385      MatProductNumeric(C);
10386 .ve
10387 
10388   Level: intermediate
10389 
10390 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10391 @*/
10392 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10393 {
10394   PetscFunctionBegin;
10395   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10396   PetscFunctionReturn(PETSC_SUCCESS);
10397 }
10398 
10399 /*@
10400   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10401 
10402   Neighbor-wise Collective
10403 
10404   Input Parameters:
10405 + A     - the left matrix
10406 . B     - the right matrix
10407 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10408 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10409 
10410   Output Parameter:
10411 . C - the product matrix
10412 
10413   Options Database Key:
10414 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10415               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10416               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10417 
10418   Level: intermediate
10419 
10420   Notes:
10421   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10422 
10423   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10424 
10425   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10426   actually needed.
10427 
10428   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10429   and for pairs of `MATMPIDENSE` matrices.
10430 
10431   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10432 
10433   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10434 
10435 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10436 @*/
10437 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10438 {
10439   PetscFunctionBegin;
10440   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10441   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10442   PetscFunctionReturn(PETSC_SUCCESS);
10443 }
10444 
10445 /*@
10446   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10447 
10448   Neighbor-wise Collective
10449 
10450   Input Parameters:
10451 + A     - the left matrix
10452 . B     - the right matrix
10453 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10454 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10455 
10456   Output Parameter:
10457 . C - the product matrix
10458 
10459   Level: intermediate
10460 
10461   Notes:
10462   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10463 
10464   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10465 
10466   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10467 
10468   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10469   actually needed.
10470 
10471   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10472   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10473 
10474   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10475 
10476 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10477 @*/
10478 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10479 {
10480   PetscFunctionBegin;
10481   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10482   PetscFunctionReturn(PETSC_SUCCESS);
10483 }
10484 
10485 /*@
10486   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10487 
10488   Neighbor-wise Collective
10489 
10490   Input Parameters:
10491 + A     - the left matrix
10492 . B     - the middle matrix
10493 . C     - the right matrix
10494 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10495 - 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
10496           if the result is a dense matrix this is irrelevant
10497 
10498   Output Parameter:
10499 . D - the product matrix
10500 
10501   Level: intermediate
10502 
10503   Notes:
10504   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10505 
10506   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10507 
10508   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10509 
10510   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10511   actually needed.
10512 
10513   If you have many matrices with the same non-zero structure to multiply, you
10514   should use `MAT_REUSE_MATRIX` in all calls but the first
10515 
10516   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10517 
10518 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10519 @*/
10520 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10521 {
10522   PetscFunctionBegin;
10523   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10524   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10525 
10526   if (scall == MAT_INITIAL_MATRIX) {
10527     PetscCall(MatProductCreate(A, B, C, D));
10528     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10529     PetscCall(MatProductSetAlgorithm(*D, "default"));
10530     PetscCall(MatProductSetFill(*D, fill));
10531 
10532     (*D)->product->api_user = PETSC_TRUE;
10533     PetscCall(MatProductSetFromOptions(*D));
10534     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,
10535                ((PetscObject)C)->type_name);
10536     PetscCall(MatProductSymbolic(*D));
10537   } else { /* user may change input matrices when REUSE */
10538     PetscCall(MatProductReplaceMats(A, B, C, *D));
10539   }
10540   PetscCall(MatProductNumeric(*D));
10541   PetscFunctionReturn(PETSC_SUCCESS);
10542 }
10543 
10544 /*@
10545   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10546 
10547   Collective
10548 
10549   Input Parameters:
10550 + mat      - the matrix
10551 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10552 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10553 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10554 
10555   Output Parameter:
10556 . matredundant - redundant matrix
10557 
10558   Level: advanced
10559 
10560   Notes:
10561   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10562   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10563 
10564   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10565   calling it.
10566 
10567   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10568 
10569 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10570 @*/
10571 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10572 {
10573   MPI_Comm       comm;
10574   PetscMPIInt    size;
10575   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10576   Mat_Redundant *redund     = NULL;
10577   PetscSubcomm   psubcomm   = NULL;
10578   MPI_Comm       subcomm_in = subcomm;
10579   Mat           *matseq;
10580   IS             isrow, iscol;
10581   PetscBool      newsubcomm = PETSC_FALSE;
10582 
10583   PetscFunctionBegin;
10584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10585   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10586     PetscAssertPointer(*matredundant, 5);
10587     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10588   }
10589 
10590   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10591   if (size == 1 || nsubcomm == 1) {
10592     if (reuse == MAT_INITIAL_MATRIX) {
10593       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10594     } else {
10595       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");
10596       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10597     }
10598     PetscFunctionReturn(PETSC_SUCCESS);
10599   }
10600 
10601   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10602   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10603   MatCheckPreallocated(mat, 1);
10604 
10605   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10606   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10607     /* create psubcomm, then get subcomm */
10608     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10609     PetscCallMPI(MPI_Comm_size(comm, &size));
10610     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10611 
10612     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10613     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10614     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10615     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10616     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10617     newsubcomm = PETSC_TRUE;
10618     PetscCall(PetscSubcommDestroy(&psubcomm));
10619   }
10620 
10621   /* get isrow, iscol and a local sequential matrix matseq[0] */
10622   if (reuse == MAT_INITIAL_MATRIX) {
10623     mloc_sub = PETSC_DECIDE;
10624     nloc_sub = PETSC_DECIDE;
10625     if (bs < 1) {
10626       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10627       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10628     } else {
10629       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10630       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10631     }
10632     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10633     rstart = rend - mloc_sub;
10634     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10635     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10636     PetscCall(ISSetIdentity(iscol));
10637   } else { /* reuse == MAT_REUSE_MATRIX */
10638     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");
10639     /* retrieve subcomm */
10640     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10641     redund = (*matredundant)->redundant;
10642     isrow  = redund->isrow;
10643     iscol  = redund->iscol;
10644     matseq = redund->matseq;
10645   }
10646   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10647 
10648   /* get matredundant over subcomm */
10649   if (reuse == MAT_INITIAL_MATRIX) {
10650     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10651 
10652     /* create a supporting struct and attach it to C for reuse */
10653     PetscCall(PetscNew(&redund));
10654     (*matredundant)->redundant = redund;
10655     redund->isrow              = isrow;
10656     redund->iscol              = iscol;
10657     redund->matseq             = matseq;
10658     if (newsubcomm) {
10659       redund->subcomm = subcomm;
10660     } else {
10661       redund->subcomm = MPI_COMM_NULL;
10662     }
10663   } else {
10664     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10665   }
10666 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10667   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10668     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10669     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10670   }
10671 #endif
10672   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10673   PetscFunctionReturn(PETSC_SUCCESS);
10674 }
10675 
10676 /*@C
10677   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10678   a given `Mat`. Each submatrix can span multiple procs.
10679 
10680   Collective
10681 
10682   Input Parameters:
10683 + mat     - the matrix
10684 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10685 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10686 
10687   Output Parameter:
10688 . subMat - parallel sub-matrices each spanning a given `subcomm`
10689 
10690   Level: advanced
10691 
10692   Notes:
10693   The submatrix partition across processors is dictated by `subComm` a
10694   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10695   is not restricted to be grouped with consecutive original MPI processes.
10696 
10697   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10698   map directly to the layout of the original matrix [wrt the local
10699   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10700   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10701   the `subMat`. However the offDiagMat looses some columns - and this is
10702   reconstructed with `MatSetValues()`
10703 
10704   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10705 
10706 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10707 @*/
10708 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10709 {
10710   PetscMPIInt commsize, subCommSize;
10711 
10712   PetscFunctionBegin;
10713   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10714   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10715   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10716 
10717   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");
10718   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10719   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10720   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10721   PetscFunctionReturn(PETSC_SUCCESS);
10722 }
10723 
10724 /*@
10725   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10726 
10727   Not Collective
10728 
10729   Input Parameters:
10730 + mat   - matrix to extract local submatrix from
10731 . isrow - local row indices for submatrix
10732 - iscol - local column indices for submatrix
10733 
10734   Output Parameter:
10735 . submat - the submatrix
10736 
10737   Level: intermediate
10738 
10739   Notes:
10740   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10741 
10742   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10743   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10744 
10745   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10746   `MatSetValuesBlockedLocal()` will also be implemented.
10747 
10748   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10749   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10750 
10751 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10752 @*/
10753 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10754 {
10755   PetscFunctionBegin;
10756   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10757   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10758   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10759   PetscCheckSameComm(isrow, 2, iscol, 3);
10760   PetscAssertPointer(submat, 4);
10761   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10762 
10763   if (mat->ops->getlocalsubmatrix) {
10764     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10765   } else {
10766     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10767   }
10768   PetscFunctionReturn(PETSC_SUCCESS);
10769 }
10770 
10771 /*@
10772   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10773 
10774   Not Collective
10775 
10776   Input Parameters:
10777 + mat    - matrix to extract local submatrix from
10778 . isrow  - local row indices for submatrix
10779 . iscol  - local column indices for submatrix
10780 - submat - the submatrix
10781 
10782   Level: intermediate
10783 
10784 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10785 @*/
10786 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10787 {
10788   PetscFunctionBegin;
10789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10790   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10791   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10792   PetscCheckSameComm(isrow, 2, iscol, 3);
10793   PetscAssertPointer(submat, 4);
10794   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10795 
10796   if (mat->ops->restorelocalsubmatrix) {
10797     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10798   } else {
10799     PetscCall(MatDestroy(submat));
10800   }
10801   *submat = NULL;
10802   PetscFunctionReturn(PETSC_SUCCESS);
10803 }
10804 
10805 /*@
10806   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10807 
10808   Collective
10809 
10810   Input Parameter:
10811 . mat - the matrix
10812 
10813   Output Parameter:
10814 . is - if any rows have zero diagonals this contains the list of them
10815 
10816   Level: developer
10817 
10818 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10819 @*/
10820 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10821 {
10822   PetscFunctionBegin;
10823   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10824   PetscValidType(mat, 1);
10825   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10826   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10827 
10828   if (!mat->ops->findzerodiagonals) {
10829     Vec                diag;
10830     const PetscScalar *a;
10831     PetscInt          *rows;
10832     PetscInt           rStart, rEnd, r, nrow = 0;
10833 
10834     PetscCall(MatCreateVecs(mat, &diag, NULL));
10835     PetscCall(MatGetDiagonal(mat, diag));
10836     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10837     PetscCall(VecGetArrayRead(diag, &a));
10838     for (r = 0; r < rEnd - rStart; ++r)
10839       if (a[r] == 0.0) ++nrow;
10840     PetscCall(PetscMalloc1(nrow, &rows));
10841     nrow = 0;
10842     for (r = 0; r < rEnd - rStart; ++r)
10843       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10844     PetscCall(VecRestoreArrayRead(diag, &a));
10845     PetscCall(VecDestroy(&diag));
10846     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10847   } else {
10848     PetscUseTypeMethod(mat, findzerodiagonals, is);
10849   }
10850   PetscFunctionReturn(PETSC_SUCCESS);
10851 }
10852 
10853 /*@
10854   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10855 
10856   Collective
10857 
10858   Input Parameter:
10859 . mat - the matrix
10860 
10861   Output Parameter:
10862 . is - contains the list of rows with off block diagonal entries
10863 
10864   Level: developer
10865 
10866 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10867 @*/
10868 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10869 {
10870   PetscFunctionBegin;
10871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10872   PetscValidType(mat, 1);
10873   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10874   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10875 
10876   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10877   PetscFunctionReturn(PETSC_SUCCESS);
10878 }
10879 
10880 /*@C
10881   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10882 
10883   Collective; No Fortran Support
10884 
10885   Input Parameter:
10886 . mat - the matrix
10887 
10888   Output Parameter:
10889 . values - the block inverses in column major order (FORTRAN-like)
10890 
10891   Level: advanced
10892 
10893   Notes:
10894   The size of the blocks is determined by the block size of the matrix.
10895 
10896   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10897 
10898   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10899 
10900 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10901 @*/
10902 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10903 {
10904   PetscFunctionBegin;
10905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10906   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10907   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10908   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10909   PetscFunctionReturn(PETSC_SUCCESS);
10910 }
10911 
10912 /*@
10913   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10914 
10915   Collective; No Fortran Support
10916 
10917   Input Parameters:
10918 + mat     - the matrix
10919 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10920 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10921 
10922   Output Parameter:
10923 . values - the block inverses in column major order (FORTRAN-like)
10924 
10925   Level: advanced
10926 
10927   Notes:
10928   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10929 
10930   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10931 
10932 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10933 @*/
10934 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10935 {
10936   PetscFunctionBegin;
10937   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10938   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10939   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10940   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10941   PetscFunctionReturn(PETSC_SUCCESS);
10942 }
10943 
10944 /*@
10945   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10946 
10947   Collective
10948 
10949   Input Parameters:
10950 + A - the matrix
10951 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10952 
10953   Level: advanced
10954 
10955   Note:
10956   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10957 
10958 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10959 @*/
10960 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10961 {
10962   const PetscScalar *vals;
10963   PetscInt          *dnnz;
10964   PetscInt           m, rstart, rend, bs, i, j;
10965 
10966   PetscFunctionBegin;
10967   PetscCall(MatInvertBlockDiagonal(A, &vals));
10968   PetscCall(MatGetBlockSize(A, &bs));
10969   PetscCall(MatGetLocalSize(A, &m, NULL));
10970   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10971   if (A->rmap->bs > 1) PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); // mpiaij to A and B
10972   PetscCall(PetscMalloc1(m / bs, &dnnz));
10973   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10974   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10975   PetscCall(PetscFree(dnnz));
10976   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10977   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10978   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10979   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10980   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10981   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10982   PetscFunctionReturn(PETSC_SUCCESS);
10983 }
10984 
10985 /*@
10986   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10987   via `MatTransposeColoringCreate()`.
10988 
10989   Collective
10990 
10991   Input Parameter:
10992 . c - coloring context
10993 
10994   Level: intermediate
10995 
10996 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10997 @*/
10998 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10999 {
11000   MatTransposeColoring matcolor = *c;
11001 
11002   PetscFunctionBegin;
11003   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
11004   if (--((PetscObject)matcolor)->refct > 0) {
11005     matcolor = NULL;
11006     PetscFunctionReturn(PETSC_SUCCESS);
11007   }
11008 
11009   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
11010   PetscCall(PetscFree(matcolor->rows));
11011   PetscCall(PetscFree(matcolor->den2sp));
11012   PetscCall(PetscFree(matcolor->colorforcol));
11013   PetscCall(PetscFree(matcolor->columns));
11014   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
11015   PetscCall(PetscHeaderDestroy(c));
11016   PetscFunctionReturn(PETSC_SUCCESS);
11017 }
11018 
11019 /*@
11020   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
11021   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
11022   `MatTransposeColoring` to sparse `B`.
11023 
11024   Collective
11025 
11026   Input Parameters:
11027 + coloring - coloring context created with `MatTransposeColoringCreate()`
11028 - B        - sparse matrix
11029 
11030   Output Parameter:
11031 . Btdense - dense matrix $B^T$
11032 
11033   Level: developer
11034 
11035   Note:
11036   These are used internally for some implementations of `MatRARt()`
11037 
11038 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
11039 @*/
11040 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
11041 {
11042   PetscFunctionBegin;
11043   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11044   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
11045   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
11046 
11047   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
11048   PetscFunctionReturn(PETSC_SUCCESS);
11049 }
11050 
11051 /*@
11052   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
11053   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
11054   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
11055   $C_{sp}$ from $C_{den}$.
11056 
11057   Collective
11058 
11059   Input Parameters:
11060 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
11061 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
11062 
11063   Output Parameter:
11064 . Csp - sparse matrix
11065 
11066   Level: developer
11067 
11068   Note:
11069   These are used internally for some implementations of `MatRARt()`
11070 
11071 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
11072 @*/
11073 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
11074 {
11075   PetscFunctionBegin;
11076   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11077   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
11078   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
11079 
11080   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
11081   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
11082   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
11083   PetscFunctionReturn(PETSC_SUCCESS);
11084 }
11085 
11086 /*@
11087   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
11088 
11089   Collective
11090 
11091   Input Parameters:
11092 + mat        - the matrix product C
11093 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
11094 
11095   Output Parameter:
11096 . color - the new coloring context
11097 
11098   Level: intermediate
11099 
11100 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11101           `MatTransColoringApplyDenToSp()`
11102 @*/
11103 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11104 {
11105   MatTransposeColoring c;
11106   MPI_Comm             comm;
11107 
11108   PetscFunctionBegin;
11109   PetscAssertPointer(color, 3);
11110 
11111   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11112   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11113   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11114   c->ctype = iscoloring->ctype;
11115   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11116   *color = c;
11117   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11118   PetscFunctionReturn(PETSC_SUCCESS);
11119 }
11120 
11121 /*@
11122   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11123   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11124 
11125   Not Collective
11126 
11127   Input Parameter:
11128 . mat - the matrix
11129 
11130   Output Parameter:
11131 . state - the current state
11132 
11133   Level: intermediate
11134 
11135   Notes:
11136   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11137   different matrices
11138 
11139   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11140 
11141   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11142 
11143 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11144 @*/
11145 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11146 {
11147   PetscFunctionBegin;
11148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11149   *state = mat->nonzerostate;
11150   PetscFunctionReturn(PETSC_SUCCESS);
11151 }
11152 
11153 /*@
11154   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11155   matrices from each processor
11156 
11157   Collective
11158 
11159   Input Parameters:
11160 + comm   - the communicators the parallel matrix will live on
11161 . seqmat - the input sequential matrices
11162 . n      - number of local columns (or `PETSC_DECIDE`)
11163 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11164 
11165   Output Parameter:
11166 . mpimat - the parallel matrix generated
11167 
11168   Level: developer
11169 
11170   Note:
11171   The number of columns of the matrix in EACH processor MUST be the same.
11172 
11173 .seealso: [](ch_matrices), `Mat`
11174 @*/
11175 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11176 {
11177   PetscMPIInt size;
11178 
11179   PetscFunctionBegin;
11180   PetscCallMPI(MPI_Comm_size(comm, &size));
11181   if (size == 1) {
11182     if (reuse == MAT_INITIAL_MATRIX) {
11183       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11184     } else {
11185       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11186     }
11187     PetscFunctionReturn(PETSC_SUCCESS);
11188   }
11189 
11190   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");
11191 
11192   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11193   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11194   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11195   PetscFunctionReturn(PETSC_SUCCESS);
11196 }
11197 
11198 /*@
11199   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11200 
11201   Collective
11202 
11203   Input Parameters:
11204 + A - the matrix to create subdomains from
11205 - N - requested number of subdomains
11206 
11207   Output Parameters:
11208 + n   - number of subdomains resulting on this MPI process
11209 - iss - `IS` list with indices of subdomains on this MPI process
11210 
11211   Level: advanced
11212 
11213   Note:
11214   The number of subdomains must be smaller than the communicator size
11215 
11216 .seealso: [](ch_matrices), `Mat`, `IS`
11217 @*/
11218 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11219 {
11220   MPI_Comm    comm, subcomm;
11221   PetscMPIInt size, rank, color;
11222   PetscInt    rstart, rend, k;
11223 
11224   PetscFunctionBegin;
11225   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11226   PetscCallMPI(MPI_Comm_size(comm, &size));
11227   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11228   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);
11229   *n    = 1;
11230   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
11231   color = rank / k;
11232   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11233   PetscCall(PetscMalloc1(1, iss));
11234   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11235   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11236   PetscCallMPI(MPI_Comm_free(&subcomm));
11237   PetscFunctionReturn(PETSC_SUCCESS);
11238 }
11239 
11240 /*@
11241   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11242 
11243   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11244   If they are not the same, uses `MatMatMatMult()`.
11245 
11246   Once the coarse grid problem is constructed, correct for interpolation operators
11247   that are not of full rank, which can legitimately happen in the case of non-nested
11248   geometric multigrid.
11249 
11250   Input Parameters:
11251 + restrct     - restriction operator
11252 . dA          - fine grid matrix
11253 . interpolate - interpolation operator
11254 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11255 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11256 
11257   Output Parameter:
11258 . A - the Galerkin coarse matrix
11259 
11260   Options Database Key:
11261 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11262 
11263   Level: developer
11264 
11265   Note:
11266   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11267 
11268 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11269 @*/
11270 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11271 {
11272   IS  zerorows;
11273   Vec diag;
11274 
11275   PetscFunctionBegin;
11276   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11277   /* Construct the coarse grid matrix */
11278   if (interpolate == restrct) {
11279     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11280   } else {
11281     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11282   }
11283 
11284   /* If the interpolation matrix is not of full rank, A will have zero rows.
11285      This can legitimately happen in the case of non-nested geometric multigrid.
11286      In that event, we set the rows of the matrix to the rows of the identity,
11287      ignoring the equations (as the RHS will also be zero). */
11288 
11289   PetscCall(MatFindZeroRows(*A, &zerorows));
11290 
11291   if (zerorows != NULL) { /* if there are any zero rows */
11292     PetscCall(MatCreateVecs(*A, &diag, NULL));
11293     PetscCall(MatGetDiagonal(*A, diag));
11294     PetscCall(VecISSet(diag, zerorows, 1.0));
11295     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11296     PetscCall(VecDestroy(&diag));
11297     PetscCall(ISDestroy(&zerorows));
11298   }
11299   PetscFunctionReturn(PETSC_SUCCESS);
11300 }
11301 
11302 /*@C
11303   MatSetOperation - Allows user to set a matrix operation for any matrix type
11304 
11305   Logically Collective
11306 
11307   Input Parameters:
11308 + mat - the matrix
11309 . op  - the name of the operation
11310 - f   - the function that provides the operation
11311 
11312   Level: developer
11313 
11314   Example Usage:
11315 .vb
11316   extern PetscErrorCode usermult(Mat, Vec, Vec);
11317 
11318   PetscCall(MatCreateXXX(comm, ..., &A));
11319   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11320 .ve
11321 
11322   Notes:
11323   See the file `include/petscmat.h` for a complete list of matrix
11324   operations, which all have the form MATOP_<OPERATION>, where
11325   <OPERATION> is the name (in all capital letters) of the
11326   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11327 
11328   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11329   sequence as the usual matrix interface routines, since they
11330   are intended to be accessed via the usual matrix interface
11331   routines, e.g.,
11332 .vb
11333   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11334 .ve
11335 
11336   In particular each function MUST return `PETSC_SUCCESS` on success and
11337   nonzero on failure.
11338 
11339   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11340 
11341 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11342 @*/
11343 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11344 {
11345   PetscFunctionBegin;
11346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11347   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11348   (((void (**)(void))mat->ops)[op]) = f;
11349   PetscFunctionReturn(PETSC_SUCCESS);
11350 }
11351 
11352 /*@C
11353   MatGetOperation - Gets a matrix operation for any matrix type.
11354 
11355   Not Collective
11356 
11357   Input Parameters:
11358 + mat - the matrix
11359 - op  - the name of the operation
11360 
11361   Output Parameter:
11362 . f - the function that provides the operation
11363 
11364   Level: developer
11365 
11366   Example Usage:
11367 .vb
11368   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11369 
11370   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11371 .ve
11372 
11373   Notes:
11374   See the file include/petscmat.h for a complete list of matrix
11375   operations, which all have the form MATOP_<OPERATION>, where
11376   <OPERATION> is the name (in all capital letters) of the
11377   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11378 
11379   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11380 
11381 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11382 @*/
11383 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11384 {
11385   PetscFunctionBegin;
11386   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11387   *f = (((void (**)(void))mat->ops)[op]);
11388   PetscFunctionReturn(PETSC_SUCCESS);
11389 }
11390 
11391 /*@
11392   MatHasOperation - Determines whether the given matrix supports the particular operation.
11393 
11394   Not Collective
11395 
11396   Input Parameters:
11397 + mat - the matrix
11398 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11399 
11400   Output Parameter:
11401 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11402 
11403   Level: advanced
11404 
11405   Note:
11406   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11407 
11408 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11409 @*/
11410 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11411 {
11412   PetscFunctionBegin;
11413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11414   PetscAssertPointer(has, 3);
11415   if (mat->ops->hasoperation) {
11416     PetscUseTypeMethod(mat, hasoperation, op, has);
11417   } else {
11418     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11419     else {
11420       *has = PETSC_FALSE;
11421       if (op == MATOP_CREATE_SUBMATRIX) {
11422         PetscMPIInt size;
11423 
11424         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11425         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11426       }
11427     }
11428   }
11429   PetscFunctionReturn(PETSC_SUCCESS);
11430 }
11431 
11432 /*@
11433   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11434 
11435   Collective
11436 
11437   Input Parameter:
11438 . mat - the matrix
11439 
11440   Output Parameter:
11441 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11442 
11443   Level: beginner
11444 
11445 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11446 @*/
11447 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11448 {
11449   PetscFunctionBegin;
11450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11451   PetscValidType(mat, 1);
11452   PetscAssertPointer(cong, 2);
11453   if (!mat->rmap || !mat->cmap) {
11454     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11455     PetscFunctionReturn(PETSC_SUCCESS);
11456   }
11457   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11458     PetscCall(PetscLayoutSetUp(mat->rmap));
11459     PetscCall(PetscLayoutSetUp(mat->cmap));
11460     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11461     if (*cong) mat->congruentlayouts = 1;
11462     else mat->congruentlayouts = 0;
11463   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11464   PetscFunctionReturn(PETSC_SUCCESS);
11465 }
11466 
11467 PetscErrorCode MatSetInf(Mat A)
11468 {
11469   PetscFunctionBegin;
11470   PetscUseTypeMethod(A, setinf);
11471   PetscFunctionReturn(PETSC_SUCCESS);
11472 }
11473 
11474 /*@
11475   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
11476   and possibly removes small values from the graph structure.
11477 
11478   Collective
11479 
11480   Input Parameters:
11481 + A       - the matrix
11482 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11483 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11484 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11485 . num_idx - size of 'index' array
11486 - index   - array of block indices to use for graph strength of connection weight
11487 
11488   Output Parameter:
11489 . graph - the resulting graph
11490 
11491   Level: advanced
11492 
11493 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11494 @*/
11495 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11496 {
11497   PetscFunctionBegin;
11498   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11499   PetscValidType(A, 1);
11500   PetscValidLogicalCollectiveBool(A, scale, 3);
11501   PetscAssertPointer(graph, 7);
11502   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11503   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11504   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11505   PetscFunctionReturn(PETSC_SUCCESS);
11506 }
11507 
11508 /*@
11509   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11510   meaning the same memory is used for the matrix, and no new memory is allocated.
11511 
11512   Collective
11513 
11514   Input Parameters:
11515 + A    - the matrix
11516 - 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
11517 
11518   Level: intermediate
11519 
11520   Developer Note:
11521   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11522   of the arrays in the data structure are unneeded.
11523 
11524 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11525 @*/
11526 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11527 {
11528   PetscFunctionBegin;
11529   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11530   PetscUseTypeMethod(A, eliminatezeros, keep);
11531   PetscFunctionReturn(PETSC_SUCCESS);
11532 }
11533