xref: /petsc/src/mat/interface/matrix.c (revision e91c04dfc8a52dee1965211bb1cc8e5bf775178f)
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   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
674   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
675   if (ncols) *ncols = 0;
676   if (cols) *cols = NULL;
677   if (vals) *vals = NULL;
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
684 
685   Not Collective
686 
687   Input Parameter:
688 . mat - the matrix
689 
690   Level: advanced
691 
692   Note:
693   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.
694 
695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
696 @*/
697 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
698 {
699   PetscFunctionBegin;
700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
701   PetscValidType(mat, 1);
702   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
703   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
704   MatCheckPreallocated(mat, 1);
705   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
706   PetscUseTypeMethod(mat, getrowuppertriangular);
707   PetscFunctionReturn(PETSC_SUCCESS);
708 }
709 
710 /*@
711   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
712 
713   Not Collective
714 
715   Input Parameter:
716 . mat - the matrix
717 
718   Level: advanced
719 
720   Note:
721   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
722 
723 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
724 @*/
725 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
726 {
727   PetscFunctionBegin;
728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
729   PetscValidType(mat, 1);
730   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
731   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
732   MatCheckPreallocated(mat, 1);
733   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
734   PetscUseTypeMethod(mat, restorerowuppertriangular);
735   PetscFunctionReturn(PETSC_SUCCESS);
736 }
737 
738 /*@
739   MatSetOptionsPrefix - Sets the prefix used for searching for all
740   `Mat` options in the database.
741 
742   Logically Collective
743 
744   Input Parameters:
745 + A      - the matrix
746 - prefix - the prefix to prepend to all option names
747 
748   Level: advanced
749 
750   Notes:
751   A hyphen (-) must NOT be given at the beginning of the prefix name.
752   The first character of all runtime options is AUTOMATICALLY the hyphen.
753 
754   This is NOT used for options for the factorization of the matrix. Normally the
755   prefix is automatically passed in from the PC calling the factorization. To set
756   it directly use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
765   PetscFunctionReturn(PETSC_SUCCESS);
766 }
767 
768 /*@
769   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
770   for matrices created with `MatGetFactor()`
771 
772   Logically Collective
773 
774   Input Parameters:
775 + A      - the matrix
776 - prefix - the prefix to prepend to all option names for the factored matrix
777 
778   Level: developer
779 
780   Notes:
781   A hyphen (-) must NOT be given at the beginning of the prefix name.
782   The first character of all runtime options is AUTOMATICALLY the hyphen.
783 
784   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
785   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
786 
787 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
788 @*/
789 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
790 {
791   PetscFunctionBegin;
792   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
793   if (prefix) {
794     PetscAssertPointer(prefix, 2);
795     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
796     if (prefix != A->factorprefix) {
797       PetscCall(PetscFree(A->factorprefix));
798       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
799     }
800   } else PetscCall(PetscFree(A->factorprefix));
801   PetscFunctionReturn(PETSC_SUCCESS);
802 }
803 
804 /*@
805   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
806   for matrices created with `MatGetFactor()`
807 
808   Logically Collective
809 
810   Input Parameters:
811 + A      - the matrix
812 - prefix - the prefix to prepend to all option names for the factored matrix
813 
814   Level: developer
815 
816   Notes:
817   A hyphen (-) must NOT be given at the beginning of the prefix name.
818   The first character of all runtime options is AUTOMATICALLY the hyphen.
819 
820   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
821   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
822 
823 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
824           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
825           `MatSetOptionsPrefix()`
826 @*/
827 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
828 {
829   size_t len1, len2, new_len;
830 
831   PetscFunctionBegin;
832   PetscValidHeader(A, 1);
833   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
834   if (!A->factorprefix) {
835     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
836     PetscFunctionReturn(PETSC_SUCCESS);
837   }
838   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
839 
840   PetscCall(PetscStrlen(A->factorprefix, &len1));
841   PetscCall(PetscStrlen(prefix, &len2));
842   new_len = len1 + len2 + 1;
843   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
844   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
845   PetscFunctionReturn(PETSC_SUCCESS);
846 }
847 
848 /*@
849   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
850   matrix options in the database.
851 
852   Logically Collective
853 
854   Input Parameters:
855 + A      - the matrix
856 - prefix - the prefix to prepend to all option names
857 
858   Level: advanced
859 
860   Note:
861   A hyphen (-) must NOT be given at the beginning of the prefix name.
862   The first character of all runtime options is AUTOMATICALLY the hyphen.
863 
864 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
865 @*/
866 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
867 {
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
870   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875   MatGetOptionsPrefix - Gets the prefix used for searching for all
876   matrix options in the database.
877 
878   Not Collective
879 
880   Input Parameter:
881 . A - the matrix
882 
883   Output Parameter:
884 . prefix - pointer to the prefix string used
885 
886   Level: advanced
887 
888   Fortran Note:
889   The user should pass in a string `prefix` of
890   sufficient length to hold the prefix.
891 
892 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
893 @*/
894 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
898   PetscAssertPointer(prefix, 2);
899   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
900   PetscFunctionReturn(PETSC_SUCCESS);
901 }
902 
903 /*@
904   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
905 
906   Not Collective
907 
908   Input Parameter:
909 . A - the matrix
910 
911   Output Parameter:
912 . state - the object state
913 
914   Level: advanced
915 
916   Note:
917   Object state is an integer which gets increased every time
918   the object is changed. By saving and later querying the object state
919   one can determine whether information about the object is still current.
920 
921   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
922 
923 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
924 @*/
925 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   PetscAssertPointer(state, 2);
930   PetscCall(PetscObjectStateGet((PetscObject)A, state));
931   PetscFunctionReturn(PETSC_SUCCESS);
932 }
933 
934 /*@
935   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
936 
937   Collective
938 
939   Input Parameter:
940 . A - the matrix
941 
942   Level: beginner
943 
944   Notes:
945   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
946   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
947   makes all of the preallocation space available
948 
949   Current values in the matrix are lost in this call.
950 
951   Currently only supported for  `MATAIJ` matrices.
952 
953 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
954 @*/
955 PetscErrorCode MatResetPreallocation(Mat A)
956 {
957   PetscFunctionBegin;
958   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
959   PetscValidType(A, 1);
960   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()");
961   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
962   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
963   PetscFunctionReturn(PETSC_SUCCESS);
964 }
965 
966 /*@
967   MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
968 
969   Collective
970 
971   Input Parameter:
972 . A - the matrix
973 
974   Level: intermediate
975 
976   Notes:
977   The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
978 
979   Currently only supported for `MATAIJ` matrices.
980 
981 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
982 @*/
983 PetscErrorCode MatResetHash(Mat A)
984 {
985   PetscFunctionBegin;
986   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
987   PetscValidType(A, 1);
988   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()");
989   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
990   PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
991   /* These flags are used to determine whether certain setups occur */
992   A->was_assembled = PETSC_FALSE;
993   A->assembled     = PETSC_FALSE;
994   /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
995   PetscCall(PetscObjectStateIncrease((PetscObject)A));
996   PetscFunctionReturn(PETSC_SUCCESS);
997 }
998 
999 /*@
1000   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
1001 
1002   Collective
1003 
1004   Input Parameter:
1005 . A - the matrix
1006 
1007   Level: advanced
1008 
1009   Notes:
1010   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
1011   setting values in the matrix.
1012 
1013   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
1014 
1015 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
1016 @*/
1017 PetscErrorCode MatSetUp(Mat A)
1018 {
1019   PetscFunctionBegin;
1020   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1021   if (!((PetscObject)A)->type_name) {
1022     PetscMPIInt size;
1023 
1024     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1025     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
1026   }
1027   if (!A->preallocated) PetscTryTypeMethod(A, setup);
1028   PetscCall(PetscLayoutSetUp(A->rmap));
1029   PetscCall(PetscLayoutSetUp(A->cmap));
1030   A->preallocated = PETSC_TRUE;
1031   PetscFunctionReturn(PETSC_SUCCESS);
1032 }
1033 
1034 #if defined(PETSC_HAVE_SAWS)
1035   #include <petscviewersaws.h>
1036 #endif
1037 
1038 /*
1039    If threadsafety is on extraneous matrices may be printed
1040 
1041    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1042 */
1043 #if !defined(PETSC_HAVE_THREADSAFETY)
1044 static PetscInt insidematview = 0;
1045 #endif
1046 
1047 /*@
1048   MatViewFromOptions - View properties of the matrix based on options set in the options database
1049 
1050   Collective
1051 
1052   Input Parameters:
1053 + A    - the matrix
1054 . obj  - optional additional object that provides the options prefix to use
1055 - name - command line option
1056 
1057   Options Database Key:
1058 . -mat_view [viewertype]:... - the viewer and its options
1059 
1060   Level: intermediate
1061 
1062   Note:
1063 .vb
1064     If no value is provided ascii:stdout is used
1065        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1066                                                   for example ascii::ascii_info prints just the information about the object not all details
1067                                                   unless :append is given filename opens in write mode, overwriting what was already there
1068        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1069        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1070        socket[:port]                             defaults to the standard output port
1071        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1072 .ve
1073 
1074 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1075 @*/
1076 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1077 {
1078   PetscFunctionBegin;
1079   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1080 #if !defined(PETSC_HAVE_THREADSAFETY)
1081   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1082 #endif
1083   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1084   PetscFunctionReturn(PETSC_SUCCESS);
1085 }
1086 
1087 /*@
1088   MatView - display information about a matrix in a variety ways
1089 
1090   Collective on viewer
1091 
1092   Input Parameters:
1093 + mat    - the matrix
1094 - viewer - visualization context
1095 
1096   Options Database Keys:
1097 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1098 . -mat_view ::ascii_info_detail    - Prints more detailed info
1099 . -mat_view                        - Prints matrix in ASCII format
1100 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1101 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1102 . -display <name>                  - Sets display name (default is host)
1103 . -draw_pause <sec>                - Sets number of seconds to pause after display
1104 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1105 . -viewer_socket_machine <machine> - -
1106 . -viewer_socket_port <port>       - -
1107 . -mat_view binary                 - save matrix to file in binary format
1108 - -viewer_binary_filename <name>   - -
1109 
1110   Level: beginner
1111 
1112   Notes:
1113   The available visualization contexts include
1114 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1115 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1116 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1117 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1118 
1119   The user can open alternative visualization contexts with
1120 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1121 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1122 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1123 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1124 
1125   The user can call `PetscViewerPushFormat()` to specify the output
1126   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1127   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1128 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1129 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1130 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1131 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1132 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1133 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1134 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1135 
1136   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1137   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1138 
1139   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1140 
1141   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1142   viewer is used.
1143 
1144   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1145   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1146 
1147   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1148   and then use the following mouse functions.
1149 .vb
1150   left mouse: zoom in
1151   middle mouse: zoom out
1152   right mouse: continue with the simulation
1153 .ve
1154 
1155 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1156           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1157 @*/
1158 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1159 {
1160   PetscInt          rows, cols, rbs, cbs;
1161   PetscBool         isascii, isstring, issaws;
1162   PetscViewerFormat format;
1163   PetscMPIInt       size;
1164 
1165   PetscFunctionBegin;
1166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1167   PetscValidType(mat, 1);
1168   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1169   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1170 
1171   PetscCall(PetscViewerGetFormat(viewer, &format));
1172   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1173   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1174 
1175 #if !defined(PETSC_HAVE_THREADSAFETY)
1176   insidematview++;
1177 #endif
1178   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1179   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1180   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1181   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");
1182 
1183   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1184   if (isascii) {
1185     if (!mat->preallocated) {
1186       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1187 #if !defined(PETSC_HAVE_THREADSAFETY)
1188       insidematview--;
1189 #endif
1190       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1191       PetscFunctionReturn(PETSC_SUCCESS);
1192     }
1193     if (!mat->assembled) {
1194       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1195 #if !defined(PETSC_HAVE_THREADSAFETY)
1196       insidematview--;
1197 #endif
1198       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1199       PetscFunctionReturn(PETSC_SUCCESS);
1200     }
1201     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1202     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1203       MatNullSpace nullsp, transnullsp;
1204 
1205       PetscCall(PetscViewerASCIIPushTab(viewer));
1206       PetscCall(MatGetSize(mat, &rows, &cols));
1207       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1208       if (rbs != 1 || cbs != 1) {
1209         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" : ""));
1210         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1211       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1212       if (mat->factortype) {
1213         MatSolverType solver;
1214         PetscCall(MatFactorGetSolverType(mat, &solver));
1215         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1216       }
1217       if (mat->ops->getinfo) {
1218         MatInfo info;
1219         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1220         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1221         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1222       }
1223       PetscCall(MatGetNullSpace(mat, &nullsp));
1224       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1225       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1226       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1227       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1228       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1229       PetscCall(PetscViewerASCIIPushTab(viewer));
1230       PetscCall(MatProductView(mat, viewer));
1231       PetscCall(PetscViewerASCIIPopTab(viewer));
1232       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1233         IS tmp;
1234 
1235         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1236         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1237         PetscCall(PetscViewerASCIIPushTab(viewer));
1238         PetscCall(ISView(tmp, viewer));
1239         PetscCall(PetscViewerASCIIPopTab(viewer));
1240         PetscCall(ISDestroy(&tmp));
1241       }
1242     }
1243   } else if (issaws) {
1244 #if defined(PETSC_HAVE_SAWS)
1245     PetscMPIInt rank;
1246 
1247     PetscCall(PetscObjectName((PetscObject)mat));
1248     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1249     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1250 #endif
1251   } else if (isstring) {
1252     const char *type;
1253     PetscCall(MatGetType(mat, &type));
1254     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1255     PetscTryTypeMethod(mat, view, viewer);
1256   }
1257   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1258     PetscCall(PetscViewerASCIIPushTab(viewer));
1259     PetscUseTypeMethod(mat, viewnative, viewer);
1260     PetscCall(PetscViewerASCIIPopTab(viewer));
1261   } else if (mat->ops->view) {
1262     PetscCall(PetscViewerASCIIPushTab(viewer));
1263     PetscUseTypeMethod(mat, view, viewer);
1264     PetscCall(PetscViewerASCIIPopTab(viewer));
1265   }
1266   if (isascii) {
1267     PetscCall(PetscViewerGetFormat(viewer, &format));
1268     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1269   }
1270   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1271 #if !defined(PETSC_HAVE_THREADSAFETY)
1272   insidematview--;
1273 #endif
1274   PetscFunctionReturn(PETSC_SUCCESS);
1275 }
1276 
1277 #if defined(PETSC_USE_DEBUG)
1278   #include <../src/sys/totalview/tv_data_display.h>
1279 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1280 {
1281   TV_add_row("Local rows", "int", &mat->rmap->n);
1282   TV_add_row("Local columns", "int", &mat->cmap->n);
1283   TV_add_row("Global rows", "int", &mat->rmap->N);
1284   TV_add_row("Global columns", "int", &mat->cmap->N);
1285   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1286   return TV_format_OK;
1287 }
1288 #endif
1289 
1290 /*@
1291   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1292   with `MatView()`.  The matrix format is determined from the options database.
1293   Generates a parallel MPI matrix if the communicator has more than one
1294   processor.  The default matrix type is `MATAIJ`.
1295 
1296   Collective
1297 
1298   Input Parameters:
1299 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1300             or some related function before a call to `MatLoad()`
1301 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1302 
1303   Options Database Key:
1304 . -matload_block_size <bs> - set block size
1305 
1306   Level: beginner
1307 
1308   Notes:
1309   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1310   `Mat` before calling this routine if you wish to set it from the options database.
1311 
1312   `MatLoad()` automatically loads into the options database any options
1313   given in the file filename.info where filename is the name of the file
1314   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1315   file will be ignored if you use the -viewer_binary_skip_info option.
1316 
1317   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1318   sets the default matrix type AIJ and sets the local and global sizes.
1319   If type and/or size is already set, then the same are used.
1320 
1321   In parallel, each processor can load a subset of rows (or the
1322   entire matrix).  This routine is especially useful when a large
1323   matrix is stored on disk and only part of it is desired on each
1324   processor.  For example, a parallel solver may access only some of
1325   the rows from each processor.  The algorithm used here reads
1326   relatively small blocks of data rather than reading the entire
1327   matrix and then subsetting it.
1328 
1329   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1330   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1331   or the sequence like
1332 .vb
1333     `PetscViewer` v;
1334     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1335     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1336     `PetscViewerSetFromOptions`(v);
1337     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1338     `PetscViewerFileSetName`(v,"datafile");
1339 .ve
1340   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1341 $ -viewer_type {binary, hdf5}
1342 
1343   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1344   and src/mat/tutorials/ex10.c with the second approach.
1345 
1346   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1347   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1348   Multiple objects, both matrices and vectors, can be stored within the same file.
1349   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1350 
1351   Most users should not need to know the details of the binary storage
1352   format, since `MatLoad()` and `MatView()` completely hide these details.
1353   But for anyone who is interested, the standard binary matrix storage
1354   format is
1355 
1356 .vb
1357     PetscInt    MAT_FILE_CLASSID
1358     PetscInt    number of rows
1359     PetscInt    number of columns
1360     PetscInt    total number of nonzeros
1361     PetscInt    *number nonzeros in each row
1362     PetscInt    *column indices of all nonzeros (starting index is zero)
1363     PetscScalar *values of all nonzeros
1364 .ve
1365   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1366   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
1367   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1368 
1369   PETSc automatically does the byte swapping for
1370   machines that store the bytes reversed. Thus if you write your own binary
1371   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1372   and `PetscBinaryWrite()` to see how this may be done.
1373 
1374   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1375   Each processor's chunk is loaded independently by its owning MPI process.
1376   Multiple objects, both matrices and vectors, can be stored within the same file.
1377   They are looked up by their PetscObject name.
1378 
1379   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1380   by default the same structure and naming of the AIJ arrays and column count
1381   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1382 $    save example.mat A b -v7.3
1383   can be directly read by this routine (see Reference 1 for details).
1384 
1385   Depending on your MATLAB version, this format might be a default,
1386   otherwise you can set it as default in Preferences.
1387 
1388   Unless -nocompression flag is used to save the file in MATLAB,
1389   PETSc must be configured with ZLIB package.
1390 
1391   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1392 
1393   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1394 
1395   Corresponding `MatView()` is not yet implemented.
1396 
1397   The loaded matrix is actually a transpose of the original one in MATLAB,
1398   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1399   With this format, matrix is automatically transposed by PETSc,
1400   unless the matrix is marked as SPD or symmetric
1401   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1402 
1403   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1404 
1405 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1406  @*/
1407 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1408 {
1409   PetscBool flg;
1410 
1411   PetscFunctionBegin;
1412   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1413   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1414 
1415   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1416 
1417   flg = PETSC_FALSE;
1418   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1419   if (flg) {
1420     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1421     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1422   }
1423   flg = PETSC_FALSE;
1424   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1425   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1426 
1427   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1428   PetscUseTypeMethod(mat, load, viewer);
1429   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1430   PetscFunctionReturn(PETSC_SUCCESS);
1431 }
1432 
1433 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1434 {
1435   Mat_Redundant *redund = *redundant;
1436 
1437   PetscFunctionBegin;
1438   if (redund) {
1439     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1440       PetscCall(ISDestroy(&redund->isrow));
1441       PetscCall(ISDestroy(&redund->iscol));
1442       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1443     } else {
1444       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1445       PetscCall(PetscFree(redund->sbuf_j));
1446       PetscCall(PetscFree(redund->sbuf_a));
1447       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1448         PetscCall(PetscFree(redund->rbuf_j[i]));
1449         PetscCall(PetscFree(redund->rbuf_a[i]));
1450       }
1451       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1452     }
1453 
1454     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1455     PetscCall(PetscFree(redund));
1456   }
1457   PetscFunctionReturn(PETSC_SUCCESS);
1458 }
1459 
1460 /*@
1461   MatDestroy - Frees space taken by a matrix.
1462 
1463   Collective
1464 
1465   Input Parameter:
1466 . A - the matrix
1467 
1468   Level: beginner
1469 
1470   Developer Note:
1471   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1472   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1473   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1474   if changes are needed here.
1475 
1476 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1477 @*/
1478 PetscErrorCode MatDestroy(Mat *A)
1479 {
1480   PetscFunctionBegin;
1481   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1482   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1483   if (--((PetscObject)*A)->refct > 0) {
1484     *A = NULL;
1485     PetscFunctionReturn(PETSC_SUCCESS);
1486   }
1487 
1488   /* if memory was published with SAWs then destroy it */
1489   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1490   PetscTryTypeMethod(*A, destroy);
1491 
1492   PetscCall(PetscFree((*A)->factorprefix));
1493   PetscCall(PetscFree((*A)->defaultvectype));
1494   PetscCall(PetscFree((*A)->defaultrandtype));
1495   PetscCall(PetscFree((*A)->bsizes));
1496   PetscCall(PetscFree((*A)->solvertype));
1497   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1498   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1499   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1500   PetscCall(MatProductClear(*A));
1501   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1502   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1503   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1504   PetscCall(MatDestroy(&(*A)->schur));
1505   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1506   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1507   PetscCall(PetscHeaderDestroy(A));
1508   PetscFunctionReturn(PETSC_SUCCESS);
1509 }
1510 
1511 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1512 /*@
1513   MatSetValues - Inserts or adds a block of values into a matrix.
1514   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1515   MUST be called after all calls to `MatSetValues()` have been completed.
1516 
1517   Not Collective
1518 
1519   Input Parameters:
1520 + mat  - the matrix
1521 . v    - a logically two-dimensional array of values
1522 . m    - the number of rows
1523 . idxm - the global indices of the rows
1524 . n    - the number of columns
1525 . idxn - the global indices of the columns
1526 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1527 
1528   Level: beginner
1529 
1530   Notes:
1531   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1532 
1533   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1534   options cannot be mixed without intervening calls to the assembly
1535   routines.
1536 
1537   `MatSetValues()` uses 0-based row and column numbers in Fortran
1538   as well as in C.
1539 
1540   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1541   simply ignored. This allows easily inserting element stiffness matrices
1542   with homogeneous Dirichlet boundary conditions that you don't want represented
1543   in the matrix.
1544 
1545   Efficiency Alert:
1546   The routine `MatSetValuesBlocked()` may offer much better efficiency
1547   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1548 
1549   Fortran Notes:
1550   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1551 .vb
1552   MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
1553 .ve
1554 
1555   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1556 
1557   Developer Note:
1558   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1559   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1560 
1561 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1562           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1563 @*/
1564 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1565 {
1566   PetscFunctionBeginHot;
1567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1568   PetscValidType(mat, 1);
1569   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1570   PetscAssertPointer(idxm, 3);
1571   PetscAssertPointer(idxn, 5);
1572   MatCheckPreallocated(mat, 1);
1573 
1574   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1575   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1576 
1577   if (PetscDefined(USE_DEBUG)) {
1578     PetscInt i, j;
1579 
1580     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1581     if (v) {
1582       for (i = 0; i < m; i++) {
1583         for (j = 0; j < n; j++) {
1584           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1585 #if defined(PETSC_USE_COMPLEX)
1586             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]);
1587 #else
1588             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]);
1589 #endif
1590         }
1591       }
1592     }
1593     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);
1594     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);
1595   }
1596 
1597   if (mat->assembled) {
1598     mat->was_assembled = PETSC_TRUE;
1599     mat->assembled     = PETSC_FALSE;
1600   }
1601   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1602   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1603   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1604   PetscFunctionReturn(PETSC_SUCCESS);
1605 }
1606 
1607 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1608 /*@
1609   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1610   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1611   MUST be called after all calls to `MatSetValues()` have been completed.
1612 
1613   Not Collective
1614 
1615   Input Parameters:
1616 + mat  - the matrix
1617 . v    - a logically two-dimensional array of values
1618 . ism  - the rows to provide
1619 . isn  - the columns to provide
1620 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1621 
1622   Level: beginner
1623 
1624   Notes:
1625   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1626 
1627   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1628   options cannot be mixed without intervening calls to the assembly
1629   routines.
1630 
1631   `MatSetValues()` uses 0-based row and column numbers in Fortran
1632   as well as in C.
1633 
1634   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1635   simply ignored. This allows easily inserting element stiffness matrices
1636   with homogeneous Dirichlet boundary conditions that you don't want represented
1637   in the matrix.
1638 
1639   Efficiency Alert:
1640   The routine `MatSetValuesBlocked()` may offer much better efficiency
1641   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1642 
1643   This is currently not optimized for any particular `ISType`
1644 
1645   Developer Note:
1646   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1647   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1648 
1649 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1650           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1651 @*/
1652 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1653 {
1654   PetscInt        m, n;
1655   const PetscInt *rows, *cols;
1656 
1657   PetscFunctionBeginHot;
1658   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1659   PetscCall(ISGetIndices(ism, &rows));
1660   PetscCall(ISGetIndices(isn, &cols));
1661   PetscCall(ISGetLocalSize(ism, &m));
1662   PetscCall(ISGetLocalSize(isn, &n));
1663   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1664   PetscCall(ISRestoreIndices(ism, &rows));
1665   PetscCall(ISRestoreIndices(isn, &cols));
1666   PetscFunctionReturn(PETSC_SUCCESS);
1667 }
1668 
1669 /*@
1670   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1671   values into a matrix
1672 
1673   Not Collective
1674 
1675   Input Parameters:
1676 + mat - the matrix
1677 . row - the (block) row to set
1678 - v   - a logically two-dimensional array of values
1679 
1680   Level: intermediate
1681 
1682   Notes:
1683   The values, `v`, are column-oriented (for the block version) and sorted
1684 
1685   All the nonzero values in `row` must be provided
1686 
1687   The matrix must have previously had its column indices set, likely by having been assembled.
1688 
1689   `row` must belong to this MPI process
1690 
1691 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1692           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1693 @*/
1694 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1695 {
1696   PetscInt globalrow;
1697 
1698   PetscFunctionBegin;
1699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1700   PetscValidType(mat, 1);
1701   PetscAssertPointer(v, 3);
1702   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1703   PetscCall(MatSetValuesRow(mat, globalrow, v));
1704   PetscFunctionReturn(PETSC_SUCCESS);
1705 }
1706 
1707 /*@
1708   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1709   values into a matrix
1710 
1711   Not Collective
1712 
1713   Input Parameters:
1714 + mat - the matrix
1715 . row - the (block) row to set
1716 - 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
1717 
1718   Level: advanced
1719 
1720   Notes:
1721   The values, `v`, are column-oriented for the block version.
1722 
1723   All the nonzeros in `row` must be provided
1724 
1725   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1726 
1727   `row` must belong to this process
1728 
1729 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1730           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1731 @*/
1732 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1733 {
1734   PetscFunctionBeginHot;
1735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1736   PetscValidType(mat, 1);
1737   MatCheckPreallocated(mat, 1);
1738   PetscAssertPointer(v, 3);
1739   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1740   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1741   mat->insertmode = INSERT_VALUES;
1742 
1743   if (mat->assembled) {
1744     mat->was_assembled = PETSC_TRUE;
1745     mat->assembled     = PETSC_FALSE;
1746   }
1747   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1748   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1749   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1750   PetscFunctionReturn(PETSC_SUCCESS);
1751 }
1752 
1753 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1754 /*@
1755   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1756   Using structured grid indexing
1757 
1758   Not Collective
1759 
1760   Input Parameters:
1761 + mat  - the matrix
1762 . m    - number of rows being entered
1763 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1764 . n    - number of columns being entered
1765 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1766 . v    - a logically two-dimensional array of values
1767 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1768 
1769   Level: beginner
1770 
1771   Notes:
1772   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1773 
1774   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1775   options cannot be mixed without intervening calls to the assembly
1776   routines.
1777 
1778   The grid coordinates are across the entire grid, not just the local portion
1779 
1780   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1781   as well as in C.
1782 
1783   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1784 
1785   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1786   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1787 
1788   The columns and rows in the stencil passed in MUST be contained within the
1789   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1790   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1791   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1792   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1793 
1794   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1795   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1796   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1797   `DM_BOUNDARY_PERIODIC` boundary type.
1798 
1799   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
1800   a single value per point) you can skip filling those indices.
1801 
1802   Inspired by the structured grid interface to the HYPRE package
1803   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1804 
1805   Efficiency Alert:
1806   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1807   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1808 
1809   Fortran Note:
1810   `idxm` and `idxn` should be declared as
1811 $     MatStencil idxm(4,m),idxn(4,n)
1812   and the values inserted using
1813 .vb
1814     idxm(MatStencil_i,1) = i
1815     idxm(MatStencil_j,1) = j
1816     idxm(MatStencil_k,1) = k
1817     idxm(MatStencil_c,1) = c
1818     etc
1819 .ve
1820 
1821 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1822           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1823 @*/
1824 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1825 {
1826   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1827   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1828   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1829 
1830   PetscFunctionBegin;
1831   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1833   PetscValidType(mat, 1);
1834   PetscAssertPointer(idxm, 3);
1835   PetscAssertPointer(idxn, 5);
1836 
1837   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1838     jdxm = buf;
1839     jdxn = buf + m;
1840   } else {
1841     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1842     jdxm = bufm;
1843     jdxn = bufn;
1844   }
1845   for (i = 0; i < m; i++) {
1846     for (j = 0; j < 3 - sdim; j++) dxm++;
1847     tmp = *dxm++ - starts[0];
1848     for (j = 0; j < dim - 1; j++) {
1849       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1850       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1851     }
1852     if (mat->stencil.noc) dxm++;
1853     jdxm[i] = tmp;
1854   }
1855   for (i = 0; i < n; i++) {
1856     for (j = 0; j < 3 - sdim; j++) dxn++;
1857     tmp = *dxn++ - starts[0];
1858     for (j = 0; j < dim - 1; j++) {
1859       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1860       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1861     }
1862     if (mat->stencil.noc) dxn++;
1863     jdxn[i] = tmp;
1864   }
1865   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1866   PetscCall(PetscFree2(bufm, bufn));
1867   PetscFunctionReturn(PETSC_SUCCESS);
1868 }
1869 
1870 /*@
1871   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1872   Using structured grid indexing
1873 
1874   Not Collective
1875 
1876   Input Parameters:
1877 + mat  - the matrix
1878 . m    - number of rows being entered
1879 . idxm - grid coordinates for matrix rows being entered
1880 . n    - number of columns being entered
1881 . idxn - grid coordinates for matrix columns being entered
1882 . v    - a logically two-dimensional array of values
1883 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1884 
1885   Level: beginner
1886 
1887   Notes:
1888   By default the values, `v`, are row-oriented and unsorted.
1889   See `MatSetOption()` for other options.
1890 
1891   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1892   options cannot be mixed without intervening calls to the assembly
1893   routines.
1894 
1895   The grid coordinates are across the entire grid, not just the local portion
1896 
1897   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1898   as well as in C.
1899 
1900   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1901 
1902   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1903   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1904 
1905   The columns and rows in the stencil passed in MUST be contained within the
1906   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1907   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1908   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1909   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1910 
1911   Negative indices may be passed in idxm and idxn, these rows and columns are
1912   simply ignored. This allows easily inserting element stiffness matrices
1913   with homogeneous Dirichlet boundary conditions that you don't want represented
1914   in the matrix.
1915 
1916   Inspired by the structured grid interface to the HYPRE package
1917   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1918 
1919   Fortran Note:
1920   `idxm` and `idxn` should be declared as
1921 $     MatStencil idxm(4,m),idxn(4,n)
1922   and the values inserted using
1923 .vb
1924     idxm(MatStencil_i,1) = i
1925     idxm(MatStencil_j,1) = j
1926     idxm(MatStencil_k,1) = k
1927    etc
1928 .ve
1929 
1930 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1931           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1932           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1933 @*/
1934 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1935 {
1936   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1937   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1938   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1939 
1940   PetscFunctionBegin;
1941   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1943   PetscValidType(mat, 1);
1944   PetscAssertPointer(idxm, 3);
1945   PetscAssertPointer(idxn, 5);
1946   PetscAssertPointer(v, 6);
1947 
1948   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1949     jdxm = buf;
1950     jdxn = buf + m;
1951   } else {
1952     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1953     jdxm = bufm;
1954     jdxn = bufn;
1955   }
1956   for (i = 0; i < m; i++) {
1957     for (j = 0; j < 3 - sdim; j++) dxm++;
1958     tmp = *dxm++ - starts[0];
1959     for (j = 0; j < sdim - 1; j++) {
1960       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1961       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1962     }
1963     dxm++;
1964     jdxm[i] = tmp;
1965   }
1966   for (i = 0; i < n; i++) {
1967     for (j = 0; j < 3 - sdim; j++) dxn++;
1968     tmp = *dxn++ - starts[0];
1969     for (j = 0; j < sdim - 1; j++) {
1970       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1971       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1972     }
1973     dxn++;
1974     jdxn[i] = tmp;
1975   }
1976   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1977   PetscCall(PetscFree2(bufm, bufn));
1978   PetscFunctionReturn(PETSC_SUCCESS);
1979 }
1980 
1981 /*@
1982   MatSetStencil - Sets the grid information for setting values into a matrix via
1983   `MatSetValuesStencil()`
1984 
1985   Not Collective
1986 
1987   Input Parameters:
1988 + mat    - the matrix
1989 . dim    - dimension of the grid 1, 2, or 3
1990 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1991 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1992 - dof    - number of degrees of freedom per node
1993 
1994   Level: beginner
1995 
1996   Notes:
1997   Inspired by the structured grid interface to the HYPRE package
1998   (www.llnl.gov/CASC/hyper)
1999 
2000   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
2001   user.
2002 
2003 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
2004           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
2005 @*/
2006 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
2007 {
2008   PetscFunctionBegin;
2009   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2010   PetscAssertPointer(dims, 3);
2011   PetscAssertPointer(starts, 4);
2012 
2013   mat->stencil.dim = dim + (dof > 1);
2014   for (PetscInt i = 0; i < dim; i++) {
2015     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
2016     mat->stencil.starts[i] = starts[dim - i - 1];
2017   }
2018   mat->stencil.dims[dim]   = dof;
2019   mat->stencil.starts[dim] = 0;
2020   mat->stencil.noc         = (PetscBool)(dof == 1);
2021   PetscFunctionReturn(PETSC_SUCCESS);
2022 }
2023 
2024 /*@
2025   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
2026 
2027   Not Collective
2028 
2029   Input Parameters:
2030 + mat  - the matrix
2031 . v    - a logically two-dimensional array of values
2032 . m    - the number of block rows
2033 . idxm - the global block indices
2034 . n    - the number of block columns
2035 . idxn - the global block indices
2036 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
2037 
2038   Level: intermediate
2039 
2040   Notes:
2041   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
2042   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
2043 
2044   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
2045   NOT the total number of rows/columns; for example, if the block size is 2 and
2046   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
2047   The values in `idxm` would be 1 2; that is the first index for each block divided by
2048   the block size.
2049 
2050   You must call `MatSetBlockSize()` when constructing this matrix (before
2051   preallocating it).
2052 
2053   By default the values, `v`, are row-oriented, so the layout of
2054   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
2055 
2056   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
2057   options cannot be mixed without intervening calls to the assembly
2058   routines.
2059 
2060   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2061   as well as in C.
2062 
2063   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2064   simply ignored. This allows easily inserting element stiffness matrices
2065   with homogeneous Dirichlet boundary conditions that you don't want represented
2066   in the matrix.
2067 
2068   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2069   internal searching must be done to determine where to place the
2070   data in the matrix storage space.  By instead inserting blocks of
2071   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2072   reduced.
2073 
2074   Example:
2075 .vb
2076    Suppose m=n=2 and block size(bs) = 2 The array is
2077 
2078    1  2  | 3  4
2079    5  6  | 7  8
2080    - - - | - - -
2081    9  10 | 11 12
2082    13 14 | 15 16
2083 
2084    v[] should be passed in like
2085    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2086 
2087   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2088    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2089 .ve
2090 
2091   Fortran Notes:
2092   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2093 .vb
2094   MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
2095 .ve
2096 
2097   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2098 
2099 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2100 @*/
2101 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2102 {
2103   PetscFunctionBeginHot;
2104   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2105   PetscValidType(mat, 1);
2106   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2107   PetscAssertPointer(idxm, 3);
2108   PetscAssertPointer(idxn, 5);
2109   MatCheckPreallocated(mat, 1);
2110   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2111   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2112   if (PetscDefined(USE_DEBUG)) {
2113     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2114     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2115   }
2116   if (PetscDefined(USE_DEBUG)) {
2117     PetscInt rbs, cbs, M, N, i;
2118     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2119     PetscCall(MatGetSize(mat, &M, &N));
2120     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);
2121     for (i = 0; i < n; i++)
2122       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);
2123   }
2124   if (mat->assembled) {
2125     mat->was_assembled = PETSC_TRUE;
2126     mat->assembled     = PETSC_FALSE;
2127   }
2128   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2129   if (mat->ops->setvaluesblocked) {
2130     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2131   } else {
2132     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2133     PetscInt i, j, bs, cbs;
2134 
2135     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2136     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2137       iidxm = buf;
2138       iidxn = buf + m * bs;
2139     } else {
2140       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2141       iidxm = bufr;
2142       iidxn = bufc;
2143     }
2144     for (i = 0; i < m; i++) {
2145       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2146     }
2147     if (m != n || bs != cbs || idxm != idxn) {
2148       for (i = 0; i < n; i++) {
2149         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2150       }
2151     } else iidxn = iidxm;
2152     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2153     PetscCall(PetscFree2(bufr, bufc));
2154   }
2155   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2156   PetscFunctionReturn(PETSC_SUCCESS);
2157 }
2158 
2159 /*@
2160   MatGetValues - Gets a block of local values from a matrix.
2161 
2162   Not Collective; can only return values that are owned by the give process
2163 
2164   Input Parameters:
2165 + mat  - the matrix
2166 . v    - a logically two-dimensional array for storing the values
2167 . m    - the number of rows
2168 . idxm - the  global indices of the rows
2169 . n    - the number of columns
2170 - idxn - the global indices of the columns
2171 
2172   Level: advanced
2173 
2174   Notes:
2175   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2176   The values, `v`, are then returned in a row-oriented format,
2177   analogous to that used by default in `MatSetValues()`.
2178 
2179   `MatGetValues()` uses 0-based row and column numbers in
2180   Fortran as well as in C.
2181 
2182   `MatGetValues()` requires that the matrix has been assembled
2183   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2184   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2185   without intermediate matrix assembly.
2186 
2187   Negative row or column indices will be ignored and those locations in `v` will be
2188   left unchanged.
2189 
2190   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2191   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2192   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2193 
2194 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2195 @*/
2196 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2197 {
2198   PetscFunctionBegin;
2199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2200   PetscValidType(mat, 1);
2201   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2202   PetscAssertPointer(idxm, 3);
2203   PetscAssertPointer(idxn, 5);
2204   PetscAssertPointer(v, 6);
2205   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2206   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2207   MatCheckPreallocated(mat, 1);
2208 
2209   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2210   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2211   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2212   PetscFunctionReturn(PETSC_SUCCESS);
2213 }
2214 
2215 /*@
2216   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2217   defined previously by `MatSetLocalToGlobalMapping()`
2218 
2219   Not Collective
2220 
2221   Input Parameters:
2222 + mat  - the matrix
2223 . nrow - number of rows
2224 . irow - the row local indices
2225 . ncol - number of columns
2226 - icol - the column local indices
2227 
2228   Output Parameter:
2229 . y - a logically two-dimensional array of values
2230 
2231   Level: advanced
2232 
2233   Notes:
2234   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2235 
2236   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,
2237   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2238   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2239   with `MatSetLocalToGlobalMapping()`.
2240 
2241   Developer Note:
2242   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2243   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2244 
2245 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2246           `MatSetValuesLocal()`, `MatGetValues()`
2247 @*/
2248 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2249 {
2250   PetscFunctionBeginHot;
2251   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2252   PetscValidType(mat, 1);
2253   MatCheckPreallocated(mat, 1);
2254   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2255   PetscAssertPointer(irow, 3);
2256   PetscAssertPointer(icol, 5);
2257   if (PetscDefined(USE_DEBUG)) {
2258     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2259     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2260   }
2261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2262   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2263   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2264   else {
2265     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2266     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2267       irowm = buf;
2268       icolm = buf + nrow;
2269     } else {
2270       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2271       irowm = bufr;
2272       icolm = bufc;
2273     }
2274     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2275     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2276     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2277     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2278     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2279     PetscCall(PetscFree2(bufr, bufc));
2280   }
2281   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2282   PetscFunctionReturn(PETSC_SUCCESS);
2283 }
2284 
2285 /*@
2286   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2287   the same size. Currently, this can only be called once and creates the given matrix.
2288 
2289   Not Collective
2290 
2291   Input Parameters:
2292 + mat  - the matrix
2293 . nb   - the number of blocks
2294 . bs   - the number of rows (and columns) in each block
2295 . rows - a concatenation of the rows for each block
2296 - v    - a concatenation of logically two-dimensional arrays of values
2297 
2298   Level: advanced
2299 
2300   Notes:
2301   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2302 
2303   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2304 
2305 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2306           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2307 @*/
2308 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2309 {
2310   PetscFunctionBegin;
2311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2312   PetscValidType(mat, 1);
2313   PetscAssertPointer(rows, 4);
2314   PetscAssertPointer(v, 5);
2315   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2316 
2317   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2318   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2319   else {
2320     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2321   }
2322   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2323   PetscFunctionReturn(PETSC_SUCCESS);
2324 }
2325 
2326 /*@
2327   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2328   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2329   using a local (per-processor) numbering.
2330 
2331   Not Collective
2332 
2333   Input Parameters:
2334 + x        - the matrix
2335 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2336 - cmapping - column mapping
2337 
2338   Level: intermediate
2339 
2340   Note:
2341   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2342 
2343 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2344 @*/
2345 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2346 {
2347   PetscFunctionBegin;
2348   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2349   PetscValidType(x, 1);
2350   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2351   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2352   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2353   else {
2354     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2355     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2356   }
2357   PetscFunctionReturn(PETSC_SUCCESS);
2358 }
2359 
2360 /*@
2361   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2362 
2363   Not Collective
2364 
2365   Input Parameter:
2366 . A - the matrix
2367 
2368   Output Parameters:
2369 + rmapping - row mapping
2370 - cmapping - column mapping
2371 
2372   Level: advanced
2373 
2374 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2375 @*/
2376 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2377 {
2378   PetscFunctionBegin;
2379   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2380   PetscValidType(A, 1);
2381   if (rmapping) {
2382     PetscAssertPointer(rmapping, 2);
2383     *rmapping = A->rmap->mapping;
2384   }
2385   if (cmapping) {
2386     PetscAssertPointer(cmapping, 3);
2387     *cmapping = A->cmap->mapping;
2388   }
2389   PetscFunctionReturn(PETSC_SUCCESS);
2390 }
2391 
2392 /*@
2393   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2394 
2395   Logically Collective
2396 
2397   Input Parameters:
2398 + A    - the matrix
2399 . rmap - row layout
2400 - cmap - column layout
2401 
2402   Level: advanced
2403 
2404   Note:
2405   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2406 
2407 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2408 @*/
2409 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2410 {
2411   PetscFunctionBegin;
2412   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2413   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2414   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2415   PetscFunctionReturn(PETSC_SUCCESS);
2416 }
2417 
2418 /*@
2419   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2420 
2421   Not Collective
2422 
2423   Input Parameter:
2424 . A - the matrix
2425 
2426   Output Parameters:
2427 + rmap - row layout
2428 - cmap - column layout
2429 
2430   Level: advanced
2431 
2432 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2433 @*/
2434 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2435 {
2436   PetscFunctionBegin;
2437   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2438   PetscValidType(A, 1);
2439   if (rmap) {
2440     PetscAssertPointer(rmap, 2);
2441     *rmap = A->rmap;
2442   }
2443   if (cmap) {
2444     PetscAssertPointer(cmap, 3);
2445     *cmap = A->cmap;
2446   }
2447   PetscFunctionReturn(PETSC_SUCCESS);
2448 }
2449 
2450 /*@
2451   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2452   using a local numbering of the rows and columns.
2453 
2454   Not Collective
2455 
2456   Input Parameters:
2457 + mat  - the matrix
2458 . nrow - number of rows
2459 . irow - the row local indices
2460 . ncol - number of columns
2461 . icol - the column local indices
2462 . y    - a logically two-dimensional array of values
2463 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2464 
2465   Level: intermediate
2466 
2467   Notes:
2468   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2469 
2470   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2471   options cannot be mixed without intervening calls to the assembly
2472   routines.
2473 
2474   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2475   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2476 
2477   Fortran Notes:
2478   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2479 .vb
2480   MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2481 .ve
2482 
2483   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2484 
2485   Developer Note:
2486   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2487   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2488 
2489 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2490           `MatGetValuesLocal()`
2491 @*/
2492 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2493 {
2494   PetscFunctionBeginHot;
2495   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2496   PetscValidType(mat, 1);
2497   MatCheckPreallocated(mat, 1);
2498   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2499   PetscAssertPointer(irow, 3);
2500   PetscAssertPointer(icol, 5);
2501   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2502   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2503   if (PetscDefined(USE_DEBUG)) {
2504     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2505     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2506   }
2507 
2508   if (mat->assembled) {
2509     mat->was_assembled = PETSC_TRUE;
2510     mat->assembled     = PETSC_FALSE;
2511   }
2512   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2513   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2514   else {
2515     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2516     const PetscInt *irowm, *icolm;
2517 
2518     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2519       bufr  = buf;
2520       bufc  = buf + nrow;
2521       irowm = bufr;
2522       icolm = bufc;
2523     } else {
2524       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2525       irowm = bufr;
2526       icolm = bufc;
2527     }
2528     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2529     else irowm = irow;
2530     if (mat->cmap->mapping) {
2531       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2532         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2533       } else icolm = irowm;
2534     } else icolm = icol;
2535     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2536     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2537   }
2538   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2539   PetscFunctionReturn(PETSC_SUCCESS);
2540 }
2541 
2542 /*@
2543   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2544   using a local ordering of the nodes a block at a time.
2545 
2546   Not Collective
2547 
2548   Input Parameters:
2549 + mat  - the matrix
2550 . nrow - number of rows
2551 . irow - the row local indices
2552 . ncol - number of columns
2553 . icol - the column local indices
2554 . y    - a logically two-dimensional array of values
2555 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2556 
2557   Level: intermediate
2558 
2559   Notes:
2560   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2561   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2562 
2563   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2564   options cannot be mixed without intervening calls to the assembly
2565   routines.
2566 
2567   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2568   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2569 
2570   Fortran Notes:
2571   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2572 .vb
2573   MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2574 .ve
2575 
2576   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2577 
2578   Developer Note:
2579   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2580   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2581 
2582 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2583           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2584 @*/
2585 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2586 {
2587   PetscFunctionBeginHot;
2588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2589   PetscValidType(mat, 1);
2590   MatCheckPreallocated(mat, 1);
2591   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2592   PetscAssertPointer(irow, 3);
2593   PetscAssertPointer(icol, 5);
2594   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2595   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2596   if (PetscDefined(USE_DEBUG)) {
2597     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2598     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);
2599   }
2600 
2601   if (mat->assembled) {
2602     mat->was_assembled = PETSC_TRUE;
2603     mat->assembled     = PETSC_FALSE;
2604   }
2605   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2606     PetscInt irbs, rbs;
2607     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2608     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2609     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2610   }
2611   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2612     PetscInt icbs, cbs;
2613     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2614     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2615     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2616   }
2617   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2618   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2619   else {
2620     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2621     const PetscInt *irowm, *icolm;
2622 
2623     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2624       bufr  = buf;
2625       bufc  = buf + nrow;
2626       irowm = bufr;
2627       icolm = bufc;
2628     } else {
2629       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2630       irowm = bufr;
2631       icolm = bufc;
2632     }
2633     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2634     else irowm = irow;
2635     if (mat->cmap->mapping) {
2636       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2637         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2638       } else icolm = irowm;
2639     } else icolm = icol;
2640     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2641     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2642   }
2643   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2644   PetscFunctionReturn(PETSC_SUCCESS);
2645 }
2646 
2647 /*@
2648   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2649 
2650   Collective
2651 
2652   Input Parameters:
2653 + mat - the matrix
2654 - x   - the vector to be multiplied
2655 
2656   Output Parameter:
2657 . y - the result
2658 
2659   Level: developer
2660 
2661   Note:
2662   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2663   call `MatMultDiagonalBlock`(A,y,y).
2664 
2665 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2666 @*/
2667 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2668 {
2669   PetscFunctionBegin;
2670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2671   PetscValidType(mat, 1);
2672   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2673   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2674 
2675   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2676   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2677   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2678   MatCheckPreallocated(mat, 1);
2679 
2680   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2681   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2682   PetscFunctionReturn(PETSC_SUCCESS);
2683 }
2684 
2685 /*@
2686   MatMult - Computes the matrix-vector product, $y = Ax$.
2687 
2688   Neighbor-wise Collective
2689 
2690   Input Parameters:
2691 + mat - the matrix
2692 - x   - the vector to be multiplied
2693 
2694   Output Parameter:
2695 . y - the result
2696 
2697   Level: beginner
2698 
2699   Note:
2700   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2701   call `MatMult`(A,y,y).
2702 
2703 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2704 @*/
2705 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2706 {
2707   PetscFunctionBegin;
2708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2709   PetscValidType(mat, 1);
2710   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2711   VecCheckAssembled(x);
2712   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2713   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2714   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2715   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2716   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);
2717   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);
2718   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);
2719   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);
2720   PetscCall(VecSetErrorIfLocked(y, 3));
2721   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2722   MatCheckPreallocated(mat, 1);
2723 
2724   PetscCall(VecLockReadPush(x));
2725   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2726   PetscUseTypeMethod(mat, mult, x, y);
2727   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2728   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2729   PetscCall(VecLockReadPop(x));
2730   PetscFunctionReturn(PETSC_SUCCESS);
2731 }
2732 
2733 /*@
2734   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2735 
2736   Neighbor-wise Collective
2737 
2738   Input Parameters:
2739 + mat - the matrix
2740 - x   - the vector to be multiplied
2741 
2742   Output Parameter:
2743 . y - the result
2744 
2745   Level: beginner
2746 
2747   Notes:
2748   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2749   call `MatMultTranspose`(A,y,y).
2750 
2751   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2752   use `MatMultHermitianTranspose()`
2753 
2754 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2755 @*/
2756 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2757 {
2758   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2759 
2760   PetscFunctionBegin;
2761   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2762   PetscValidType(mat, 1);
2763   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2764   VecCheckAssembled(x);
2765   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2766 
2767   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2768   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2769   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2770   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);
2771   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);
2772   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);
2773   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);
2774   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2775   MatCheckPreallocated(mat, 1);
2776 
2777   if (!mat->ops->multtranspose) {
2778     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2779     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);
2780   } else op = mat->ops->multtranspose;
2781   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2782   PetscCall(VecLockReadPush(x));
2783   PetscCall((*op)(mat, x, y));
2784   PetscCall(VecLockReadPop(x));
2785   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2786   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2787   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2788   PetscFunctionReturn(PETSC_SUCCESS);
2789 }
2790 
2791 /*@
2792   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2793 
2794   Neighbor-wise Collective
2795 
2796   Input Parameters:
2797 + mat - the matrix
2798 - x   - the vector to be multiplied
2799 
2800   Output Parameter:
2801 . y - the result
2802 
2803   Level: beginner
2804 
2805   Notes:
2806   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2807   call `MatMultHermitianTranspose`(A,y,y).
2808 
2809   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2810 
2811   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2812 
2813 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2814 @*/
2815 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2816 {
2817   PetscFunctionBegin;
2818   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2819   PetscValidType(mat, 1);
2820   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2821   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2822 
2823   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2824   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2825   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2826   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);
2827   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);
2828   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);
2829   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);
2830   MatCheckPreallocated(mat, 1);
2831 
2832   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2833 #if defined(PETSC_USE_COMPLEX)
2834   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2835     PetscCall(VecLockReadPush(x));
2836     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2837     else PetscUseTypeMethod(mat, mult, x, y);
2838     PetscCall(VecLockReadPop(x));
2839   } else {
2840     Vec w;
2841     PetscCall(VecDuplicate(x, &w));
2842     PetscCall(VecCopy(x, w));
2843     PetscCall(VecConjugate(w));
2844     PetscCall(MatMultTranspose(mat, w, y));
2845     PetscCall(VecDestroy(&w));
2846     PetscCall(VecConjugate(y));
2847   }
2848   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2849 #else
2850   PetscCall(MatMultTranspose(mat, x, y));
2851 #endif
2852   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2853   PetscFunctionReturn(PETSC_SUCCESS);
2854 }
2855 
2856 /*@
2857   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2858 
2859   Neighbor-wise Collective
2860 
2861   Input Parameters:
2862 + mat - the matrix
2863 . v1  - the vector to be multiplied by `mat`
2864 - v2  - the vector to be added to the result
2865 
2866   Output Parameter:
2867 . v3 - the result
2868 
2869   Level: beginner
2870 
2871   Note:
2872   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2873   call `MatMultAdd`(A,v1,v2,v1).
2874 
2875 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2876 @*/
2877 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2878 {
2879   PetscFunctionBegin;
2880   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2881   PetscValidType(mat, 1);
2882   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2883   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2884   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2885 
2886   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2887   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2888   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);
2889   /* 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);
2890      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); */
2891   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);
2892   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);
2893   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2894   MatCheckPreallocated(mat, 1);
2895 
2896   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2897   PetscCall(VecLockReadPush(v1));
2898   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2899   PetscCall(VecLockReadPop(v1));
2900   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2901   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2902   PetscFunctionReturn(PETSC_SUCCESS);
2903 }
2904 
2905 /*@
2906   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2907 
2908   Neighbor-wise Collective
2909 
2910   Input Parameters:
2911 + mat - the matrix
2912 . v1  - the vector to be multiplied by the transpose of the matrix
2913 - v2  - the vector to be added to the result
2914 
2915   Output Parameter:
2916 . v3 - the result
2917 
2918   Level: beginner
2919 
2920   Note:
2921   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2922   call `MatMultTransposeAdd`(A,v1,v2,v1).
2923 
2924 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2925 @*/
2926 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2927 {
2928   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2929 
2930   PetscFunctionBegin;
2931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2932   PetscValidType(mat, 1);
2933   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2934   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2935   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2936 
2937   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2938   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2939   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);
2940   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);
2941   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);
2942   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2943   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2944   MatCheckPreallocated(mat, 1);
2945 
2946   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2947   PetscCall(VecLockReadPush(v1));
2948   PetscCall((*op)(mat, v1, v2, v3));
2949   PetscCall(VecLockReadPop(v1));
2950   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2951   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2952   PetscFunctionReturn(PETSC_SUCCESS);
2953 }
2954 
2955 /*@
2956   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2957 
2958   Neighbor-wise Collective
2959 
2960   Input Parameters:
2961 + mat - the matrix
2962 . v1  - the vector to be multiplied by the Hermitian transpose
2963 - v2  - the vector to be added to the result
2964 
2965   Output Parameter:
2966 . v3 - the result
2967 
2968   Level: beginner
2969 
2970   Note:
2971   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2972   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2973 
2974 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2975 @*/
2976 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2977 {
2978   PetscFunctionBegin;
2979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2980   PetscValidType(mat, 1);
2981   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2982   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2983   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2984 
2985   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2986   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2987   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2988   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);
2989   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);
2990   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);
2991   MatCheckPreallocated(mat, 1);
2992 
2993   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2994   PetscCall(VecLockReadPush(v1));
2995   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2996   else {
2997     Vec w, z;
2998     PetscCall(VecDuplicate(v1, &w));
2999     PetscCall(VecCopy(v1, w));
3000     PetscCall(VecConjugate(w));
3001     PetscCall(VecDuplicate(v3, &z));
3002     PetscCall(MatMultTranspose(mat, w, z));
3003     PetscCall(VecDestroy(&w));
3004     PetscCall(VecConjugate(z));
3005     if (v2 != v3) {
3006       PetscCall(VecWAXPY(v3, 1.0, v2, z));
3007     } else {
3008       PetscCall(VecAXPY(v3, 1.0, z));
3009     }
3010     PetscCall(VecDestroy(&z));
3011   }
3012   PetscCall(VecLockReadPop(v1));
3013   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
3014   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
3015   PetscFunctionReturn(PETSC_SUCCESS);
3016 }
3017 
3018 /*@
3019   MatGetFactorType - gets the type of factorization a matrix is
3020 
3021   Not Collective
3022 
3023   Input Parameter:
3024 . mat - the matrix
3025 
3026   Output Parameter:
3027 . 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`
3028 
3029   Level: intermediate
3030 
3031 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3032           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3033 @*/
3034 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
3035 {
3036   PetscFunctionBegin;
3037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3038   PetscValidType(mat, 1);
3039   PetscAssertPointer(t, 2);
3040   *t = mat->factortype;
3041   PetscFunctionReturn(PETSC_SUCCESS);
3042 }
3043 
3044 /*@
3045   MatSetFactorType - sets the type of factorization a matrix is
3046 
3047   Logically Collective
3048 
3049   Input Parameters:
3050 + mat - the matrix
3051 - 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`
3052 
3053   Level: intermediate
3054 
3055 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3056           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3057 @*/
3058 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3059 {
3060   PetscFunctionBegin;
3061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3062   PetscValidType(mat, 1);
3063   mat->factortype = t;
3064   PetscFunctionReturn(PETSC_SUCCESS);
3065 }
3066 
3067 /*@
3068   MatGetInfo - Returns information about matrix storage (number of
3069   nonzeros, memory, etc.).
3070 
3071   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3072 
3073   Input Parameters:
3074 + mat  - the matrix
3075 - 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)
3076 
3077   Output Parameter:
3078 . info - matrix information context
3079 
3080   Options Database Key:
3081 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3082 
3083   Level: intermediate
3084 
3085   Notes:
3086   The `MatInfo` context contains a variety of matrix data, including
3087   number of nonzeros allocated and used, number of mallocs during
3088   matrix assembly, etc.  Additional information for factored matrices
3089   is provided (such as the fill ratio, number of mallocs during
3090   factorization, etc.).
3091 
3092   Example:
3093   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3094   data within the `MatInfo` context.  For example,
3095 .vb
3096       MatInfo info;
3097       Mat     A;
3098       double  mal, nz_a, nz_u;
3099 
3100       MatGetInfo(A, MAT_LOCAL, &info);
3101       mal  = info.mallocs;
3102       nz_a = info.nz_allocated;
3103 .ve
3104 
3105   Fortran Note:
3106   Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3107   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3108   a complete list of parameter names.
3109 .vb
3110       MatInfo info(MAT_INFO_SIZE)
3111       double  precision mal, nz_a
3112       Mat     A
3113       integer ierr
3114 
3115       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3116       mal = info(MAT_INFO_MALLOCS)
3117       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3118 .ve
3119 
3120 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3121 @*/
3122 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3123 {
3124   PetscFunctionBegin;
3125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3126   PetscValidType(mat, 1);
3127   PetscAssertPointer(info, 3);
3128   MatCheckPreallocated(mat, 1);
3129   PetscUseTypeMethod(mat, getinfo, flag, info);
3130   PetscFunctionReturn(PETSC_SUCCESS);
3131 }
3132 
3133 /*
3134    This is used by external packages where it is not easy to get the info from the actual
3135    matrix factorization.
3136 */
3137 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3138 {
3139   PetscFunctionBegin;
3140   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3141   PetscFunctionReturn(PETSC_SUCCESS);
3142 }
3143 
3144 /*@
3145   MatLUFactor - Performs in-place LU factorization of matrix.
3146 
3147   Collective
3148 
3149   Input Parameters:
3150 + mat  - the matrix
3151 . row  - row permutation
3152 . col  - column permutation
3153 - info - options for factorization, includes
3154 .vb
3155           fill - expected fill as ratio of original fill.
3156           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3157                    Run with the option -info to determine an optimal value to use
3158 .ve
3159 
3160   Level: developer
3161 
3162   Notes:
3163   Most users should employ the `KSP` interface for linear solvers
3164   instead of working directly with matrix algebra routines such as this.
3165   See, e.g., `KSPCreate()`.
3166 
3167   This changes the state of the matrix to a factored matrix; it cannot be used
3168   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3169 
3170   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3171   when not using `KSP`.
3172 
3173   Developer Note:
3174   The Fortran interface is not autogenerated as the
3175   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3176 
3177 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3178           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3179 @*/
3180 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3181 {
3182   MatFactorInfo tinfo;
3183 
3184   PetscFunctionBegin;
3185   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3186   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3187   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3188   if (info) PetscAssertPointer(info, 4);
3189   PetscValidType(mat, 1);
3190   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3191   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3192   MatCheckPreallocated(mat, 1);
3193   if (!info) {
3194     PetscCall(MatFactorInfoInitialize(&tinfo));
3195     info = &tinfo;
3196   }
3197 
3198   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3199   PetscUseTypeMethod(mat, lufactor, row, col, info);
3200   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3201   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3202   PetscFunctionReturn(PETSC_SUCCESS);
3203 }
3204 
3205 /*@
3206   MatILUFactor - Performs in-place ILU factorization of matrix.
3207 
3208   Collective
3209 
3210   Input Parameters:
3211 + mat  - the matrix
3212 . row  - row permutation
3213 . col  - column permutation
3214 - info - structure containing
3215 .vb
3216       levels - number of levels of fill.
3217       expected fill - as ratio of original fill.
3218       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3219                 missing diagonal entries)
3220 .ve
3221 
3222   Level: developer
3223 
3224   Notes:
3225   Most users should employ the `KSP` interface for linear solvers
3226   instead of working directly with matrix algebra routines such as this.
3227   See, e.g., `KSPCreate()`.
3228 
3229   Probably really in-place only when level of fill is zero, otherwise allocates
3230   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3231   when not using `KSP`.
3232 
3233   Developer Note:
3234   The Fortran interface is not autogenerated as the
3235   interface definition cannot be generated correctly [due to MatFactorInfo]
3236 
3237 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3238 @*/
3239 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3240 {
3241   PetscFunctionBegin;
3242   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3243   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3244   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3245   PetscAssertPointer(info, 4);
3246   PetscValidType(mat, 1);
3247   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3248   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3249   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3250   MatCheckPreallocated(mat, 1);
3251 
3252   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3253   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3254   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3255   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3256   PetscFunctionReturn(PETSC_SUCCESS);
3257 }
3258 
3259 /*@
3260   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3261   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3262 
3263   Collective
3264 
3265   Input Parameters:
3266 + fact - the factor matrix obtained with `MatGetFactor()`
3267 . mat  - the matrix
3268 . row  - the row permutation
3269 . col  - the column permutation
3270 - info - options for factorization, includes
3271 .vb
3272           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3273           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3274 .ve
3275 
3276   Level: developer
3277 
3278   Notes:
3279   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3280 
3281   Most users should employ the simplified `KSP` interface for linear solvers
3282   instead of working directly with matrix algebra routines such as this.
3283   See, e.g., `KSPCreate()`.
3284 
3285   Developer Note:
3286   The Fortran interface is not autogenerated as the
3287   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3288 
3289 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3290 @*/
3291 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3292 {
3293   MatFactorInfo tinfo;
3294 
3295   PetscFunctionBegin;
3296   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3297   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3298   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3299   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3300   if (info) PetscAssertPointer(info, 5);
3301   PetscValidType(fact, 1);
3302   PetscValidType(mat, 2);
3303   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3304   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3305   MatCheckPreallocated(mat, 2);
3306   if (!info) {
3307     PetscCall(MatFactorInfoInitialize(&tinfo));
3308     info = &tinfo;
3309   }
3310 
3311   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3312   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3313   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3314   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3315   PetscFunctionReturn(PETSC_SUCCESS);
3316 }
3317 
3318 /*@
3319   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3320   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3321 
3322   Collective
3323 
3324   Input Parameters:
3325 + fact - the factor matrix obtained with `MatGetFactor()`
3326 . mat  - the matrix
3327 - info - options for factorization
3328 
3329   Level: developer
3330 
3331   Notes:
3332   See `MatLUFactor()` for in-place factorization.  See
3333   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3334 
3335   Most users should employ the `KSP` interface for linear solvers
3336   instead of working directly with matrix algebra routines such as this.
3337   See, e.g., `KSPCreate()`.
3338 
3339   Developer Note:
3340   The Fortran interface is not autogenerated as the
3341   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3342 
3343 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3344 @*/
3345 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3346 {
3347   MatFactorInfo tinfo;
3348 
3349   PetscFunctionBegin;
3350   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3351   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3352   PetscValidType(fact, 1);
3353   PetscValidType(mat, 2);
3354   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3355   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,
3356              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3357 
3358   MatCheckPreallocated(mat, 2);
3359   if (!info) {
3360     PetscCall(MatFactorInfoInitialize(&tinfo));
3361     info = &tinfo;
3362   }
3363 
3364   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3365   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3366   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3367   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3368   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3369   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3370   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3371   PetscFunctionReturn(PETSC_SUCCESS);
3372 }
3373 
3374 /*@
3375   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3376   symmetric matrix.
3377 
3378   Collective
3379 
3380   Input Parameters:
3381 + mat  - the matrix
3382 . perm - row and column permutations
3383 - info - expected fill as ratio of original fill
3384 
3385   Level: developer
3386 
3387   Notes:
3388   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3389   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3390 
3391   Most users should employ the `KSP` interface for linear solvers
3392   instead of working directly with matrix algebra routines such as this.
3393   See, e.g., `KSPCreate()`.
3394 
3395   Developer Note:
3396   The Fortran interface is not autogenerated as the
3397   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3398 
3399 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3400           `MatGetOrdering()`
3401 @*/
3402 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3403 {
3404   MatFactorInfo tinfo;
3405 
3406   PetscFunctionBegin;
3407   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3408   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3409   if (info) PetscAssertPointer(info, 3);
3410   PetscValidType(mat, 1);
3411   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3412   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3413   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3414   MatCheckPreallocated(mat, 1);
3415   if (!info) {
3416     PetscCall(MatFactorInfoInitialize(&tinfo));
3417     info = &tinfo;
3418   }
3419 
3420   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3421   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3422   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3423   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3424   PetscFunctionReturn(PETSC_SUCCESS);
3425 }
3426 
3427 /*@
3428   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3429   of a symmetric matrix.
3430 
3431   Collective
3432 
3433   Input Parameters:
3434 + fact - the factor matrix obtained with `MatGetFactor()`
3435 . mat  - the matrix
3436 . perm - row and column permutations
3437 - info - options for factorization, includes
3438 .vb
3439           fill - expected fill as ratio of original fill.
3440           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3441                    Run with the option -info to determine an optimal value to use
3442 .ve
3443 
3444   Level: developer
3445 
3446   Notes:
3447   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3448   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3449 
3450   Most users should employ the `KSP` interface for linear solvers
3451   instead of working directly with matrix algebra routines such as this.
3452   See, e.g., `KSPCreate()`.
3453 
3454   Developer Note:
3455   The Fortran interface is not autogenerated as the
3456   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3457 
3458 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3459           `MatGetOrdering()`
3460 @*/
3461 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3462 {
3463   MatFactorInfo tinfo;
3464 
3465   PetscFunctionBegin;
3466   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3468   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3469   if (info) PetscAssertPointer(info, 4);
3470   PetscValidType(fact, 1);
3471   PetscValidType(mat, 2);
3472   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3473   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3474   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3475   MatCheckPreallocated(mat, 2);
3476   if (!info) {
3477     PetscCall(MatFactorInfoInitialize(&tinfo));
3478     info = &tinfo;
3479   }
3480 
3481   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3482   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3483   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3484   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3485   PetscFunctionReturn(PETSC_SUCCESS);
3486 }
3487 
3488 /*@
3489   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3490   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3491   `MatCholeskyFactorSymbolic()`.
3492 
3493   Collective
3494 
3495   Input Parameters:
3496 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3497 . mat  - the initial matrix that is to be factored
3498 - info - options for factorization
3499 
3500   Level: developer
3501 
3502   Note:
3503   Most users should employ the `KSP` interface for linear solvers
3504   instead of working directly with matrix algebra routines such as this.
3505   See, e.g., `KSPCreate()`.
3506 
3507   Developer Note:
3508   The Fortran interface is not autogenerated as the
3509   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3510 
3511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3512 @*/
3513 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3514 {
3515   MatFactorInfo tinfo;
3516 
3517   PetscFunctionBegin;
3518   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3519   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3520   PetscValidType(fact, 1);
3521   PetscValidType(mat, 2);
3522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3523   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,
3524              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3525   MatCheckPreallocated(mat, 2);
3526   if (!info) {
3527     PetscCall(MatFactorInfoInitialize(&tinfo));
3528     info = &tinfo;
3529   }
3530 
3531   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3532   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3533   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3534   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3535   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3536   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3537   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3538   PetscFunctionReturn(PETSC_SUCCESS);
3539 }
3540 
3541 /*@
3542   MatQRFactor - Performs in-place QR factorization of matrix.
3543 
3544   Collective
3545 
3546   Input Parameters:
3547 + mat  - the matrix
3548 . col  - column permutation
3549 - info - options for factorization, includes
3550 .vb
3551           fill - expected fill as ratio of original fill.
3552           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3553                    Run with the option -info to determine an optimal value to use
3554 .ve
3555 
3556   Level: developer
3557 
3558   Notes:
3559   Most users should employ the `KSP` interface for linear solvers
3560   instead of working directly with matrix algebra routines such as this.
3561   See, e.g., `KSPCreate()`.
3562 
3563   This changes the state of the matrix to a factored matrix; it cannot be used
3564   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3565 
3566   Developer Note:
3567   The Fortran interface is not autogenerated as the
3568   interface definition cannot be generated correctly [due to MatFactorInfo]
3569 
3570 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3571           `MatSetUnfactored()`
3572 @*/
3573 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3574 {
3575   PetscFunctionBegin;
3576   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3577   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3578   if (info) PetscAssertPointer(info, 3);
3579   PetscValidType(mat, 1);
3580   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3581   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3582   MatCheckPreallocated(mat, 1);
3583   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3584   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3585   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3586   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3587   PetscFunctionReturn(PETSC_SUCCESS);
3588 }
3589 
3590 /*@
3591   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3592   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3593 
3594   Collective
3595 
3596   Input Parameters:
3597 + fact - the factor matrix obtained with `MatGetFactor()`
3598 . mat  - the matrix
3599 . col  - column permutation
3600 - info - options for factorization, includes
3601 .vb
3602           fill - expected fill as ratio of original fill.
3603           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3604                    Run with the option -info to determine an optimal value to use
3605 .ve
3606 
3607   Level: developer
3608 
3609   Note:
3610   Most users should employ the `KSP` interface for linear solvers
3611   instead of working directly with matrix algebra routines such as this.
3612   See, e.g., `KSPCreate()`.
3613 
3614   Developer Note:
3615   The Fortran interface is not autogenerated as the
3616   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3617 
3618 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3619 @*/
3620 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3621 {
3622   MatFactorInfo tinfo;
3623 
3624   PetscFunctionBegin;
3625   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3626   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3627   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3628   if (info) PetscAssertPointer(info, 4);
3629   PetscValidType(fact, 1);
3630   PetscValidType(mat, 2);
3631   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3632   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3633   MatCheckPreallocated(mat, 2);
3634   if (!info) {
3635     PetscCall(MatFactorInfoInitialize(&tinfo));
3636     info = &tinfo;
3637   }
3638 
3639   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3640   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3641   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3642   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3643   PetscFunctionReturn(PETSC_SUCCESS);
3644 }
3645 
3646 /*@
3647   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3648   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3649 
3650   Collective
3651 
3652   Input Parameters:
3653 + fact - the factor matrix obtained with `MatGetFactor()`
3654 . mat  - the matrix
3655 - info - options for factorization
3656 
3657   Level: developer
3658 
3659   Notes:
3660   See `MatQRFactor()` for in-place factorization.
3661 
3662   Most users should employ the `KSP` interface for linear solvers
3663   instead of working directly with matrix algebra routines such as this.
3664   See, e.g., `KSPCreate()`.
3665 
3666   Developer Note:
3667   The Fortran interface is not autogenerated as the
3668   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3669 
3670 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3671 @*/
3672 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3673 {
3674   MatFactorInfo tinfo;
3675 
3676   PetscFunctionBegin;
3677   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3678   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3679   PetscValidType(fact, 1);
3680   PetscValidType(mat, 2);
3681   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3682   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,
3683              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3684 
3685   MatCheckPreallocated(mat, 2);
3686   if (!info) {
3687     PetscCall(MatFactorInfoInitialize(&tinfo));
3688     info = &tinfo;
3689   }
3690 
3691   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3692   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3693   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3694   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3695   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3696   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3697   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3698   PetscFunctionReturn(PETSC_SUCCESS);
3699 }
3700 
3701 /*@
3702   MatSolve - Solves $A x = b$, given a factored matrix.
3703 
3704   Neighbor-wise Collective
3705 
3706   Input Parameters:
3707 + mat - the factored matrix
3708 - b   - the right-hand-side vector
3709 
3710   Output Parameter:
3711 . x - the result vector
3712 
3713   Level: developer
3714 
3715   Notes:
3716   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3717   call `MatSolve`(A,x,x).
3718 
3719   Most users should employ the `KSP` interface for linear solvers
3720   instead of working directly with matrix algebra routines such as this.
3721   See, e.g., `KSPCreate()`.
3722 
3723 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3724 @*/
3725 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3726 {
3727   PetscFunctionBegin;
3728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3729   PetscValidType(mat, 1);
3730   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3731   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3732   PetscCheckSameComm(mat, 1, b, 2);
3733   PetscCheckSameComm(mat, 1, x, 3);
3734   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3735   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);
3736   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);
3737   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);
3738   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3739   MatCheckPreallocated(mat, 1);
3740 
3741   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3742   PetscCall(VecFlag(x, mat->factorerrortype));
3743   if (mat->factorerrortype) {
3744     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3745   } else PetscUseTypeMethod(mat, solve, b, x);
3746   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3747   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3748   PetscFunctionReturn(PETSC_SUCCESS);
3749 }
3750 
3751 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3752 {
3753   Vec      b, x;
3754   PetscInt N, i;
3755   PetscErrorCode (*f)(Mat, Vec, Vec);
3756   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3757 
3758   PetscFunctionBegin;
3759   if (A->factorerrortype) {
3760     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3761     PetscCall(MatSetInf(X));
3762     PetscFunctionReturn(PETSC_SUCCESS);
3763   }
3764   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3765   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3766   PetscCall(MatBoundToCPU(A, &Abound));
3767   if (!Abound) {
3768     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3769     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3770   }
3771 #if PetscDefined(HAVE_CUDA)
3772   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3773   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3774 #elif PetscDefined(HAVE_HIP)
3775   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3776   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3777 #endif
3778   PetscCall(MatGetSize(B, NULL, &N));
3779   for (i = 0; i < N; i++) {
3780     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3781     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3782     PetscCall((*f)(A, b, x));
3783     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3784     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3785   }
3786   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3787   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3788   PetscFunctionReturn(PETSC_SUCCESS);
3789 }
3790 
3791 /*@
3792   MatMatSolve - Solves $A X = B$, given a factored matrix.
3793 
3794   Neighbor-wise Collective
3795 
3796   Input Parameters:
3797 + A - the factored matrix
3798 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3799 
3800   Output Parameter:
3801 . X - the result matrix (dense matrix)
3802 
3803   Level: developer
3804 
3805   Note:
3806   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3807   otherwise, `B` and `X` cannot be the same.
3808 
3809 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3810 @*/
3811 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3812 {
3813   PetscFunctionBegin;
3814   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3815   PetscValidType(A, 1);
3816   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3817   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3818   PetscCheckSameComm(A, 1, B, 2);
3819   PetscCheckSameComm(A, 1, X, 3);
3820   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);
3821   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);
3822   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");
3823   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3824   MatCheckPreallocated(A, 1);
3825 
3826   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3827   if (!A->ops->matsolve) {
3828     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3829     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3830   } else PetscUseTypeMethod(A, matsolve, B, X);
3831   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3832   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3833   PetscFunctionReturn(PETSC_SUCCESS);
3834 }
3835 
3836 /*@
3837   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3838 
3839   Neighbor-wise Collective
3840 
3841   Input Parameters:
3842 + A - the factored matrix
3843 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3844 
3845   Output Parameter:
3846 . X - the result matrix (dense matrix)
3847 
3848   Level: developer
3849 
3850   Note:
3851   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3852   call `MatMatSolveTranspose`(A,X,X).
3853 
3854 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3855 @*/
3856 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3857 {
3858   PetscFunctionBegin;
3859   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3860   PetscValidType(A, 1);
3861   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3862   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3863   PetscCheckSameComm(A, 1, B, 2);
3864   PetscCheckSameComm(A, 1, X, 3);
3865   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3866   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);
3867   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);
3868   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);
3869   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");
3870   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3871   MatCheckPreallocated(A, 1);
3872 
3873   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3874   if (!A->ops->matsolvetranspose) {
3875     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3876     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3877   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3878   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3879   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3880   PetscFunctionReturn(PETSC_SUCCESS);
3881 }
3882 
3883 /*@
3884   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3885 
3886   Neighbor-wise Collective
3887 
3888   Input Parameters:
3889 + A  - the factored matrix
3890 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3891 
3892   Output Parameter:
3893 . X - the result matrix (dense matrix)
3894 
3895   Level: developer
3896 
3897   Note:
3898   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
3899   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3900 
3901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3902 @*/
3903 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3904 {
3905   PetscFunctionBegin;
3906   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3907   PetscValidType(A, 1);
3908   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3909   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3910   PetscCheckSameComm(A, 1, Bt, 2);
3911   PetscCheckSameComm(A, 1, X, 3);
3912 
3913   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3914   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);
3915   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);
3916   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");
3917   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3918   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3919   MatCheckPreallocated(A, 1);
3920 
3921   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3922   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3923   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3924   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3925   PetscFunctionReturn(PETSC_SUCCESS);
3926 }
3927 
3928 /*@
3929   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3930   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3931 
3932   Neighbor-wise Collective
3933 
3934   Input Parameters:
3935 + mat - the factored matrix
3936 - b   - the right-hand-side vector
3937 
3938   Output Parameter:
3939 . x - the result vector
3940 
3941   Level: developer
3942 
3943   Notes:
3944   `MatSolve()` should be used for most applications, as it performs
3945   a forward solve followed by a backward solve.
3946 
3947   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3948   call `MatForwardSolve`(A,x,x).
3949 
3950   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3951   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3952   `MatForwardSolve()` solves $U^T*D y = b$, and
3953   `MatBackwardSolve()` solves $U x = y$.
3954   Thus they do not provide a symmetric preconditioner.
3955 
3956 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3957 @*/
3958 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3959 {
3960   PetscFunctionBegin;
3961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3962   PetscValidType(mat, 1);
3963   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3964   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3965   PetscCheckSameComm(mat, 1, b, 2);
3966   PetscCheckSameComm(mat, 1, x, 3);
3967   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3968   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);
3969   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);
3970   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);
3971   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3972   MatCheckPreallocated(mat, 1);
3973 
3974   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3975   PetscUseTypeMethod(mat, forwardsolve, b, x);
3976   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3977   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3978   PetscFunctionReturn(PETSC_SUCCESS);
3979 }
3980 
3981 /*@
3982   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3983   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3984 
3985   Neighbor-wise Collective
3986 
3987   Input Parameters:
3988 + mat - the factored matrix
3989 - b   - the right-hand-side vector
3990 
3991   Output Parameter:
3992 . x - the result vector
3993 
3994   Level: developer
3995 
3996   Notes:
3997   `MatSolve()` should be used for most applications, as it performs
3998   a forward solve followed by a backward solve.
3999 
4000   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4001   call `MatBackwardSolve`(A,x,x).
4002 
4003   For matrix in `MATSEQBAIJ` format with block size larger than 1,
4004   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
4005   `MatForwardSolve()` solves $U^T*D y = b$, and
4006   `MatBackwardSolve()` solves $U x = y$.
4007   Thus they do not provide a symmetric preconditioner.
4008 
4009 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
4010 @*/
4011 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
4012 {
4013   PetscFunctionBegin;
4014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4015   PetscValidType(mat, 1);
4016   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4017   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4018   PetscCheckSameComm(mat, 1, b, 2);
4019   PetscCheckSameComm(mat, 1, x, 3);
4020   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4021   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);
4022   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);
4023   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);
4024   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4025   MatCheckPreallocated(mat, 1);
4026 
4027   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
4028   PetscUseTypeMethod(mat, backwardsolve, b, x);
4029   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
4030   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4031   PetscFunctionReturn(PETSC_SUCCESS);
4032 }
4033 
4034 /*@
4035   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
4036 
4037   Neighbor-wise Collective
4038 
4039   Input Parameters:
4040 + mat - the factored matrix
4041 . b   - the right-hand-side vector
4042 - y   - the vector to be added to
4043 
4044   Output Parameter:
4045 . x - the result vector
4046 
4047   Level: developer
4048 
4049   Note:
4050   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4051   call `MatSolveAdd`(A,x,y,x).
4052 
4053 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
4054 @*/
4055 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
4056 {
4057   PetscScalar one = 1.0;
4058   Vec         tmp;
4059 
4060   PetscFunctionBegin;
4061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4062   PetscValidType(mat, 1);
4063   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4064   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4065   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4066   PetscCheckSameComm(mat, 1, b, 2);
4067   PetscCheckSameComm(mat, 1, y, 3);
4068   PetscCheckSameComm(mat, 1, x, 4);
4069   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4070   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);
4071   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);
4072   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);
4073   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);
4074   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);
4075   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4076   MatCheckPreallocated(mat, 1);
4077 
4078   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4079   PetscCall(VecFlag(x, mat->factorerrortype));
4080   if (mat->factorerrortype) {
4081     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4082   } else if (mat->ops->solveadd) {
4083     PetscUseTypeMethod(mat, solveadd, b, y, x);
4084   } else {
4085     /* do the solve then the add manually */
4086     if (x != y) {
4087       PetscCall(MatSolve(mat, b, x));
4088       PetscCall(VecAXPY(x, one, y));
4089     } else {
4090       PetscCall(VecDuplicate(x, &tmp));
4091       PetscCall(VecCopy(x, tmp));
4092       PetscCall(MatSolve(mat, b, x));
4093       PetscCall(VecAXPY(x, one, tmp));
4094       PetscCall(VecDestroy(&tmp));
4095     }
4096   }
4097   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4098   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4099   PetscFunctionReturn(PETSC_SUCCESS);
4100 }
4101 
4102 /*@
4103   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4104 
4105   Neighbor-wise Collective
4106 
4107   Input Parameters:
4108 + mat - the factored matrix
4109 - b   - the right-hand-side vector
4110 
4111   Output Parameter:
4112 . x - the result vector
4113 
4114   Level: developer
4115 
4116   Notes:
4117   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4118   call `MatSolveTranspose`(A,x,x).
4119 
4120   Most users should employ the `KSP` interface for linear solvers
4121   instead of working directly with matrix algebra routines such as this.
4122   See, e.g., `KSPCreate()`.
4123 
4124 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4125 @*/
4126 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4127 {
4128   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4129 
4130   PetscFunctionBegin;
4131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4132   PetscValidType(mat, 1);
4133   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4134   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4135   PetscCheckSameComm(mat, 1, b, 2);
4136   PetscCheckSameComm(mat, 1, x, 3);
4137   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4138   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);
4139   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);
4140   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4141   MatCheckPreallocated(mat, 1);
4142   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4143   PetscCall(VecFlag(x, mat->factorerrortype));
4144   if (mat->factorerrortype) {
4145     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4146   } else {
4147     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4148     PetscCall((*f)(mat, b, x));
4149   }
4150   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4151   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4152   PetscFunctionReturn(PETSC_SUCCESS);
4153 }
4154 
4155 /*@
4156   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4157   factored matrix.
4158 
4159   Neighbor-wise Collective
4160 
4161   Input Parameters:
4162 + mat - the factored matrix
4163 . b   - the right-hand-side vector
4164 - y   - the vector to be added to
4165 
4166   Output Parameter:
4167 . x - the result vector
4168 
4169   Level: developer
4170 
4171   Note:
4172   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4173   call `MatSolveTransposeAdd`(A,x,y,x).
4174 
4175 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4176 @*/
4177 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4178 {
4179   PetscScalar one = 1.0;
4180   Vec         tmp;
4181   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4182 
4183   PetscFunctionBegin;
4184   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4185   PetscValidType(mat, 1);
4186   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4187   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4188   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4189   PetscCheckSameComm(mat, 1, b, 2);
4190   PetscCheckSameComm(mat, 1, y, 3);
4191   PetscCheckSameComm(mat, 1, x, 4);
4192   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4193   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);
4194   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);
4195   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);
4196   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);
4197   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4198   MatCheckPreallocated(mat, 1);
4199 
4200   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4201   PetscCall(VecFlag(x, mat->factorerrortype));
4202   if (mat->factorerrortype) {
4203     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4204   } else if (f) {
4205     PetscCall((*f)(mat, b, y, x));
4206   } else {
4207     /* do the solve then the add manually */
4208     if (x != y) {
4209       PetscCall(MatSolveTranspose(mat, b, x));
4210       PetscCall(VecAXPY(x, one, y));
4211     } else {
4212       PetscCall(VecDuplicate(x, &tmp));
4213       PetscCall(VecCopy(x, tmp));
4214       PetscCall(MatSolveTranspose(mat, b, x));
4215       PetscCall(VecAXPY(x, one, tmp));
4216       PetscCall(VecDestroy(&tmp));
4217     }
4218   }
4219   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4220   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4221   PetscFunctionReturn(PETSC_SUCCESS);
4222 }
4223 
4224 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4225 /*@
4226   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4227 
4228   Neighbor-wise Collective
4229 
4230   Input Parameters:
4231 + mat   - the matrix
4232 . b     - the right-hand side
4233 . omega - the relaxation factor
4234 . flag  - flag indicating the type of SOR (see below)
4235 . shift - diagonal shift
4236 . its   - the number of iterations
4237 - lits  - the number of local iterations
4238 
4239   Output Parameter:
4240 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4241 
4242   SOR Flags:
4243 +     `SOR_FORWARD_SWEEP` - forward SOR
4244 .     `SOR_BACKWARD_SWEEP` - backward SOR
4245 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4246 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4247 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4248 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4249 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4250 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4251   upper/lower triangular part of matrix to
4252   vector (with omega)
4253 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4254 
4255   Level: developer
4256 
4257   Notes:
4258   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4259   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4260   on each processor.
4261 
4262   Application programmers will not generally use `MatSOR()` directly,
4263   but instead will employ the `KSP`/`PC` interface.
4264 
4265   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4266 
4267   Most users should employ the `KSP` interface for linear solvers
4268   instead of working directly with matrix algebra routines such as this.
4269   See, e.g., `KSPCreate()`.
4270 
4271   Vectors `x` and `b` CANNOT be the same
4272 
4273   The flags are implemented as bitwise inclusive or operations.
4274   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4275   to specify a zero initial guess for SSOR.
4276 
4277   Developer Note:
4278   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4279 
4280 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4281 @*/
4282 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4283 {
4284   PetscFunctionBegin;
4285   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4286   PetscValidType(mat, 1);
4287   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4288   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4289   PetscCheckSameComm(mat, 1, b, 2);
4290   PetscCheckSameComm(mat, 1, x, 8);
4291   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4292   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4293   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);
4294   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);
4295   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);
4296   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4297   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4298   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4299 
4300   MatCheckPreallocated(mat, 1);
4301   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4302   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4303   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4304   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4305   PetscFunctionReturn(PETSC_SUCCESS);
4306 }
4307 
4308 /*
4309       Default matrix copy routine.
4310 */
4311 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4312 {
4313   PetscInt           i, rstart = 0, rend = 0, nz;
4314   const PetscInt    *cwork;
4315   const PetscScalar *vwork;
4316 
4317   PetscFunctionBegin;
4318   if (B->assembled) PetscCall(MatZeroEntries(B));
4319   if (str == SAME_NONZERO_PATTERN) {
4320     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4321     for (i = rstart; i < rend; i++) {
4322       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4323       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4324       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4325     }
4326   } else {
4327     PetscCall(MatAYPX(B, 0.0, A, str));
4328   }
4329   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4330   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4331   PetscFunctionReturn(PETSC_SUCCESS);
4332 }
4333 
4334 /*@
4335   MatCopy - Copies a matrix to another matrix.
4336 
4337   Collective
4338 
4339   Input Parameters:
4340 + A   - the matrix
4341 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4342 
4343   Output Parameter:
4344 . B - where the copy is put
4345 
4346   Level: intermediate
4347 
4348   Notes:
4349   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4350 
4351   `MatCopy()` copies the matrix entries of a matrix to another existing
4352   matrix (after first zeroing the second matrix).  A related routine is
4353   `MatConvert()`, which first creates a new matrix and then copies the data.
4354 
4355 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4356 @*/
4357 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4358 {
4359   PetscInt i;
4360 
4361   PetscFunctionBegin;
4362   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4363   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4364   PetscValidType(A, 1);
4365   PetscValidType(B, 2);
4366   PetscCheckSameComm(A, 1, B, 2);
4367   MatCheckPreallocated(B, 2);
4368   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4369   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4370   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,
4371              A->cmap->N, B->cmap->N);
4372   MatCheckPreallocated(A, 1);
4373   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4374 
4375   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4376   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4377   else PetscCall(MatCopy_Basic(A, B, str));
4378 
4379   B->stencil.dim = A->stencil.dim;
4380   B->stencil.noc = A->stencil.noc;
4381   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4382     B->stencil.dims[i]   = A->stencil.dims[i];
4383     B->stencil.starts[i] = A->stencil.starts[i];
4384   }
4385 
4386   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4387   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4388   PetscFunctionReturn(PETSC_SUCCESS);
4389 }
4390 
4391 /*@
4392   MatConvert - Converts a matrix to another matrix, either of the same
4393   or different type.
4394 
4395   Collective
4396 
4397   Input Parameters:
4398 + mat     - the matrix
4399 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4400             same type as the original matrix.
4401 - reuse   - denotes if the destination matrix is to be created or reused.
4402             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
4403             `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).
4404 
4405   Output Parameter:
4406 . M - pointer to place new matrix
4407 
4408   Level: intermediate
4409 
4410   Notes:
4411   `MatConvert()` first creates a new matrix and then copies the data from
4412   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4413   entries of one matrix to another already existing matrix context.
4414 
4415   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4416   the MPI communicator of the generated matrix is always the same as the communicator
4417   of the input matrix.
4418 
4419 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4420 @*/
4421 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4422 {
4423   PetscBool  sametype, issame, flg;
4424   PetscBool3 issymmetric, ishermitian;
4425   char       convname[256], mtype[256];
4426   Mat        B;
4427 
4428   PetscFunctionBegin;
4429   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4430   PetscValidType(mat, 1);
4431   PetscAssertPointer(M, 4);
4432   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4433   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4434   MatCheckPreallocated(mat, 1);
4435 
4436   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4437   if (flg) newtype = mtype;
4438 
4439   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4440   PetscCall(PetscStrcmp(newtype, "same", &issame));
4441   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4442   if (reuse == MAT_REUSE_MATRIX) {
4443     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4444     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4445   }
4446 
4447   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4448     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4449     PetscFunctionReturn(PETSC_SUCCESS);
4450   }
4451 
4452   /* Cache Mat options because some converters use MatHeaderReplace  */
4453   issymmetric = mat->symmetric;
4454   ishermitian = mat->hermitian;
4455 
4456   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4457     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4458     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4459   } else {
4460     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4461     const char *prefix[3]                                 = {"seq", "mpi", ""};
4462     PetscInt    i;
4463     /*
4464        Order of precedence:
4465        0) See if newtype is a superclass of the current matrix.
4466        1) See if a specialized converter is known to the current matrix.
4467        2) See if a specialized converter is known to the desired matrix class.
4468        3) See if a good general converter is registered for the desired class
4469           (as of 6/27/03 only MATMPIADJ falls into this category).
4470        4) See if a good general converter is known for the current matrix.
4471        5) Use a really basic converter.
4472     */
4473 
4474     /* 0) See if newtype is a superclass of the current matrix.
4475           i.e mat is mpiaij and newtype is aij */
4476     for (i = 0; i < 2; i++) {
4477       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4478       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4479       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4480       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4481       if (flg) {
4482         if (reuse == MAT_INPLACE_MATRIX) {
4483           PetscCall(PetscInfo(mat, "Early return\n"));
4484           PetscFunctionReturn(PETSC_SUCCESS);
4485         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4486           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4487           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4488           PetscFunctionReturn(PETSC_SUCCESS);
4489         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4490           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4491           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4492           PetscFunctionReturn(PETSC_SUCCESS);
4493         }
4494       }
4495     }
4496     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4497     for (i = 0; i < 3; i++) {
4498       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4499       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4500       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4501       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4502       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4503       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4504       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4505       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4506       if (conv) goto foundconv;
4507     }
4508 
4509     /* 2)  See if a specialized converter is known to the desired matrix class. */
4510     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4511     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4512     PetscCall(MatSetType(B, newtype));
4513     for (i = 0; i < 3; i++) {
4514       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4515       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4516       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4517       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4518       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4519       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4520       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4521       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4522       if (conv) {
4523         PetscCall(MatDestroy(&B));
4524         goto foundconv;
4525       }
4526     }
4527 
4528     /* 3) See if a good general converter is registered for the desired class */
4529     conv = B->ops->convertfrom;
4530     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4531     PetscCall(MatDestroy(&B));
4532     if (conv) goto foundconv;
4533 
4534     /* 4) See if a good general converter is known for the current matrix */
4535     if (mat->ops->convert) conv = mat->ops->convert;
4536     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4537     if (conv) goto foundconv;
4538 
4539     /* 5) Use a really basic converter. */
4540     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4541     conv = MatConvert_Basic;
4542 
4543   foundconv:
4544     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4545     PetscCall((*conv)(mat, newtype, reuse, M));
4546     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4547       /* the block sizes must be same if the mappings are copied over */
4548       (*M)->rmap->bs = mat->rmap->bs;
4549       (*M)->cmap->bs = mat->cmap->bs;
4550       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4551       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4552       (*M)->rmap->mapping = mat->rmap->mapping;
4553       (*M)->cmap->mapping = mat->cmap->mapping;
4554     }
4555     (*M)->stencil.dim = mat->stencil.dim;
4556     (*M)->stencil.noc = mat->stencil.noc;
4557     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4558       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4559       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4560     }
4561     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4562   }
4563   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4564 
4565   /* Copy Mat options */
4566   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4567   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4568   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4569   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4570   PetscFunctionReturn(PETSC_SUCCESS);
4571 }
4572 
4573 /*@
4574   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4575 
4576   Not Collective
4577 
4578   Input Parameter:
4579 . mat - the matrix, must be a factored matrix
4580 
4581   Output Parameter:
4582 . type - the string name of the package (do not free this string)
4583 
4584   Level: intermediate
4585 
4586   Fortran Note:
4587   Pass in an empty string that is long enough and the package name will be copied into it.
4588 
4589 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4590 @*/
4591 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4592 {
4593   PetscErrorCode (*conv)(Mat, MatSolverType *);
4594 
4595   PetscFunctionBegin;
4596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4597   PetscValidType(mat, 1);
4598   PetscAssertPointer(type, 2);
4599   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4600   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4601   if (conv) PetscCall((*conv)(mat, type));
4602   else *type = MATSOLVERPETSC;
4603   PetscFunctionReturn(PETSC_SUCCESS);
4604 }
4605 
4606 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4607 struct _MatSolverTypeForSpecifcType {
4608   MatType mtype;
4609   /* no entry for MAT_FACTOR_NONE */
4610   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4611   MatSolverTypeForSpecifcType next;
4612 };
4613 
4614 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4615 struct _MatSolverTypeHolder {
4616   char                       *name;
4617   MatSolverTypeForSpecifcType handlers;
4618   MatSolverTypeHolder         next;
4619 };
4620 
4621 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4622 
4623 /*@C
4624   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4625 
4626   Logically Collective, No Fortran Support
4627 
4628   Input Parameters:
4629 + package      - name of the package, for example petsc or superlu
4630 . mtype        - the matrix type that works with this package
4631 . ftype        - the type of factorization supported by the package
4632 - createfactor - routine that will create the factored matrix ready to be used
4633 
4634   Level: developer
4635 
4636 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4637   `MatGetFactor()`
4638 @*/
4639 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4640 {
4641   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4642   PetscBool                   flg;
4643   MatSolverTypeForSpecifcType inext, iprev = NULL;
4644 
4645   PetscFunctionBegin;
4646   PetscCall(MatInitializePackage());
4647   if (!next) {
4648     PetscCall(PetscNew(&MatSolverTypeHolders));
4649     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4650     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4651     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4652     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4653     PetscFunctionReturn(PETSC_SUCCESS);
4654   }
4655   while (next) {
4656     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4657     if (flg) {
4658       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4659       inext = next->handlers;
4660       while (inext) {
4661         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4662         if (flg) {
4663           inext->createfactor[(int)ftype - 1] = createfactor;
4664           PetscFunctionReturn(PETSC_SUCCESS);
4665         }
4666         iprev = inext;
4667         inext = inext->next;
4668       }
4669       PetscCall(PetscNew(&iprev->next));
4670       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4671       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4672       PetscFunctionReturn(PETSC_SUCCESS);
4673     }
4674     prev = next;
4675     next = next->next;
4676   }
4677   PetscCall(PetscNew(&prev->next));
4678   PetscCall(PetscStrallocpy(package, &prev->next->name));
4679   PetscCall(PetscNew(&prev->next->handlers));
4680   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4681   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4682   PetscFunctionReturn(PETSC_SUCCESS);
4683 }
4684 
4685 /*@C
4686   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4687 
4688   Input Parameters:
4689 + 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
4690 . ftype - the type of factorization supported by the type
4691 - mtype - the matrix type that works with this type
4692 
4693   Output Parameters:
4694 + foundtype    - `PETSC_TRUE` if the type was registered
4695 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4696 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4697 
4698   Calling sequence of `createfactor`:
4699 + A     - the matrix providing the factor matrix
4700 . ftype - the `MatFactorType` of the factor requested
4701 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4702 
4703   Level: developer
4704 
4705   Note:
4706   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4707   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4708   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4709 
4710 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4711           `MatInitializePackage()`
4712 @*/
4713 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4714 {
4715   MatSolverTypeHolder         next = MatSolverTypeHolders;
4716   PetscBool                   flg;
4717   MatSolverTypeForSpecifcType inext;
4718 
4719   PetscFunctionBegin;
4720   if (foundtype) *foundtype = PETSC_FALSE;
4721   if (foundmtype) *foundmtype = PETSC_FALSE;
4722   if (createfactor) *createfactor = NULL;
4723 
4724   if (type) {
4725     while (next) {
4726       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4727       if (flg) {
4728         if (foundtype) *foundtype = PETSC_TRUE;
4729         inext = next->handlers;
4730         while (inext) {
4731           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4732           if (flg) {
4733             if (foundmtype) *foundmtype = PETSC_TRUE;
4734             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4735             PetscFunctionReturn(PETSC_SUCCESS);
4736           }
4737           inext = inext->next;
4738         }
4739       }
4740       next = next->next;
4741     }
4742   } else {
4743     while (next) {
4744       inext = next->handlers;
4745       while (inext) {
4746         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4747         if (flg && inext->createfactor[(int)ftype - 1]) {
4748           if (foundtype) *foundtype = PETSC_TRUE;
4749           if (foundmtype) *foundmtype = PETSC_TRUE;
4750           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4751           PetscFunctionReturn(PETSC_SUCCESS);
4752         }
4753         inext = inext->next;
4754       }
4755       next = next->next;
4756     }
4757     /* try with base classes inext->mtype */
4758     next = MatSolverTypeHolders;
4759     while (next) {
4760       inext = next->handlers;
4761       while (inext) {
4762         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4763         if (flg && inext->createfactor[(int)ftype - 1]) {
4764           if (foundtype) *foundtype = PETSC_TRUE;
4765           if (foundmtype) *foundmtype = PETSC_TRUE;
4766           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4767           PetscFunctionReturn(PETSC_SUCCESS);
4768         }
4769         inext = inext->next;
4770       }
4771       next = next->next;
4772     }
4773   }
4774   PetscFunctionReturn(PETSC_SUCCESS);
4775 }
4776 
4777 PetscErrorCode MatSolverTypeDestroy(void)
4778 {
4779   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4780   MatSolverTypeForSpecifcType inext, iprev;
4781 
4782   PetscFunctionBegin;
4783   while (next) {
4784     PetscCall(PetscFree(next->name));
4785     inext = next->handlers;
4786     while (inext) {
4787       PetscCall(PetscFree(inext->mtype));
4788       iprev = inext;
4789       inext = inext->next;
4790       PetscCall(PetscFree(iprev));
4791     }
4792     prev = next;
4793     next = next->next;
4794     PetscCall(PetscFree(prev));
4795   }
4796   MatSolverTypeHolders = NULL;
4797   PetscFunctionReturn(PETSC_SUCCESS);
4798 }
4799 
4800 /*@
4801   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4802 
4803   Logically Collective
4804 
4805   Input Parameter:
4806 . mat - the matrix
4807 
4808   Output Parameter:
4809 . flg - `PETSC_TRUE` if uses the ordering
4810 
4811   Level: developer
4812 
4813   Note:
4814   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4815   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4816 
4817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4818 @*/
4819 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4820 {
4821   PetscFunctionBegin;
4822   *flg = mat->canuseordering;
4823   PetscFunctionReturn(PETSC_SUCCESS);
4824 }
4825 
4826 /*@
4827   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4828 
4829   Logically Collective
4830 
4831   Input Parameters:
4832 + mat   - the matrix obtained with `MatGetFactor()`
4833 - ftype - the factorization type to be used
4834 
4835   Output Parameter:
4836 . otype - the preferred ordering type
4837 
4838   Level: developer
4839 
4840 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4841 @*/
4842 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4843 {
4844   PetscFunctionBegin;
4845   *otype = mat->preferredordering[ftype];
4846   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4847   PetscFunctionReturn(PETSC_SUCCESS);
4848 }
4849 
4850 /*@
4851   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4852 
4853   Collective
4854 
4855   Input Parameters:
4856 + mat   - the matrix
4857 . 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
4858           the other criteria is returned
4859 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4860 
4861   Output Parameter:
4862 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4863 
4864   Options Database Keys:
4865 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4866 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4867                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4868 
4869   Level: intermediate
4870 
4871   Notes:
4872   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4873   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4874 
4875   Users usually access the factorization solvers via `KSP`
4876 
4877   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4878   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
4879 
4880   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4881   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4882   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4883 
4884   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4885   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4886   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4887 
4888   Developer Note:
4889   This should actually be called `MatCreateFactor()` since it creates a new factor object
4890 
4891 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4892           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4893           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4894 @*/
4895 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4896 {
4897   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4898   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4899 
4900   PetscFunctionBegin;
4901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4902   PetscValidType(mat, 1);
4903 
4904   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4905   MatCheckPreallocated(mat, 1);
4906 
4907   PetscCall(MatIsShell(mat, &shell));
4908   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4909   if (hasop) {
4910     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4911     PetscFunctionReturn(PETSC_SUCCESS);
4912   }
4913 
4914   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4915   if (!foundtype) {
4916     if (type) {
4917       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],
4918               ((PetscObject)mat)->type_name, type);
4919     } else {
4920       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);
4921     }
4922   }
4923   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4924   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);
4925 
4926   PetscCall((*conv)(mat, ftype, f));
4927   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4928   PetscFunctionReturn(PETSC_SUCCESS);
4929 }
4930 
4931 /*@
4932   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4933 
4934   Not Collective
4935 
4936   Input Parameters:
4937 + mat   - the matrix
4938 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4939 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4940 
4941   Output Parameter:
4942 . flg - PETSC_TRUE if the factorization is available
4943 
4944   Level: intermediate
4945 
4946   Notes:
4947   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4948   such as pastix, superlu, mumps etc.
4949 
4950   PETSc must have been ./configure to use the external solver, using the option --download-package
4951 
4952   Developer Note:
4953   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4954 
4955 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4956           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4957 @*/
4958 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4959 {
4960   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4961 
4962   PetscFunctionBegin;
4963   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4964   PetscAssertPointer(flg, 4);
4965 
4966   *flg = PETSC_FALSE;
4967   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4968 
4969   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4970   MatCheckPreallocated(mat, 1);
4971 
4972   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4973   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4974   PetscFunctionReturn(PETSC_SUCCESS);
4975 }
4976 
4977 /*@
4978   MatDuplicate - Duplicates a matrix including the non-zero structure.
4979 
4980   Collective
4981 
4982   Input Parameters:
4983 + mat - the matrix
4984 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4985         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4986 
4987   Output Parameter:
4988 . M - pointer to place new matrix
4989 
4990   Level: intermediate
4991 
4992   Notes:
4993   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4994 
4995   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4996 
4997   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.
4998 
4999   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
5000   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
5001   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
5002 
5003 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
5004 @*/
5005 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
5006 {
5007   Mat         B;
5008   VecType     vtype;
5009   PetscInt    i;
5010   PetscObject dm, container_h, container_d;
5011   void (*viewf)(void);
5012 
5013   PetscFunctionBegin;
5014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5015   PetscValidType(mat, 1);
5016   PetscAssertPointer(M, 3);
5017   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
5018   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5019   MatCheckPreallocated(mat, 1);
5020 
5021   *M = NULL;
5022   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
5023   PetscUseTypeMethod(mat, duplicate, op, M);
5024   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
5025   B = *M;
5026 
5027   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
5028   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
5029   PetscCall(MatGetVecType(mat, &vtype));
5030   PetscCall(MatSetVecType(B, vtype));
5031 
5032   B->stencil.dim = mat->stencil.dim;
5033   B->stencil.noc = mat->stencil.noc;
5034   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
5035     B->stencil.dims[i]   = mat->stencil.dims[i];
5036     B->stencil.starts[i] = mat->stencil.starts[i];
5037   }
5038 
5039   B->nooffproczerorows = mat->nooffproczerorows;
5040   B->nooffprocentries  = mat->nooffprocentries;
5041 
5042   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
5043   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
5044   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
5045   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
5046   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
5047   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
5048   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
5049   PetscCall(PetscObjectStateIncrease((PetscObject)B));
5050   PetscFunctionReturn(PETSC_SUCCESS);
5051 }
5052 
5053 /*@
5054   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
5055 
5056   Logically Collective
5057 
5058   Input Parameter:
5059 . mat - the matrix
5060 
5061   Output Parameter:
5062 . v - the diagonal of the matrix
5063 
5064   Level: intermediate
5065 
5066   Note:
5067   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5068   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5069   is larger than `ndiag`, the values of the remaining entries are unspecified.
5070 
5071   Currently only correct in parallel for square matrices.
5072 
5073 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5074 @*/
5075 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5076 {
5077   PetscFunctionBegin;
5078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5079   PetscValidType(mat, 1);
5080   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5081   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5082   MatCheckPreallocated(mat, 1);
5083   if (PetscDefined(USE_DEBUG)) {
5084     PetscInt nv, row, col, ndiag;
5085 
5086     PetscCall(VecGetLocalSize(v, &nv));
5087     PetscCall(MatGetLocalSize(mat, &row, &col));
5088     ndiag = PetscMin(row, col);
5089     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);
5090   }
5091 
5092   PetscUseTypeMethod(mat, getdiagonal, v);
5093   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5094   PetscFunctionReturn(PETSC_SUCCESS);
5095 }
5096 
5097 /*@
5098   MatGetRowMin - Gets the minimum value (of the real part) of each
5099   row of the matrix
5100 
5101   Logically Collective
5102 
5103   Input Parameter:
5104 . mat - the matrix
5105 
5106   Output Parameters:
5107 + v   - the vector for storing the maximums
5108 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5109 
5110   Level: intermediate
5111 
5112   Note:
5113   The result of this call are the same as if one converted the matrix to dense format
5114   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5115 
5116   This code is only implemented for a couple of matrix formats.
5117 
5118 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5119           `MatGetRowMax()`
5120 @*/
5121 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5122 {
5123   PetscFunctionBegin;
5124   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5125   PetscValidType(mat, 1);
5126   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5127   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5128 
5129   if (!mat->cmap->N) {
5130     PetscCall(VecSet(v, PETSC_MAX_REAL));
5131     if (idx) {
5132       PetscInt i, m = mat->rmap->n;
5133       for (i = 0; i < m; i++) idx[i] = -1;
5134     }
5135   } else {
5136     MatCheckPreallocated(mat, 1);
5137   }
5138   PetscUseTypeMethod(mat, getrowmin, v, idx);
5139   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5140   PetscFunctionReturn(PETSC_SUCCESS);
5141 }
5142 
5143 /*@
5144   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5145   row of the matrix
5146 
5147   Logically Collective
5148 
5149   Input Parameter:
5150 . mat - the matrix
5151 
5152   Output Parameters:
5153 + v   - the vector for storing the minimums
5154 - idx - the indices of the column found for each row (or `NULL` if not needed)
5155 
5156   Level: intermediate
5157 
5158   Notes:
5159   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5160   row is 0 (the first column).
5161 
5162   This code is only implemented for a couple of matrix formats.
5163 
5164 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5165 @*/
5166 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5167 {
5168   PetscFunctionBegin;
5169   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5170   PetscValidType(mat, 1);
5171   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5172   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5173   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5174 
5175   if (!mat->cmap->N) {
5176     PetscCall(VecSet(v, 0.0));
5177     if (idx) {
5178       PetscInt i, m = mat->rmap->n;
5179       for (i = 0; i < m; i++) idx[i] = -1;
5180     }
5181   } else {
5182     MatCheckPreallocated(mat, 1);
5183     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5184     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5185   }
5186   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5187   PetscFunctionReturn(PETSC_SUCCESS);
5188 }
5189 
5190 /*@
5191   MatGetRowMax - Gets the maximum value (of the real part) of each
5192   row of the matrix
5193 
5194   Logically Collective
5195 
5196   Input Parameter:
5197 . mat - the matrix
5198 
5199   Output Parameters:
5200 + v   - the vector for storing the maximums
5201 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5202 
5203   Level: intermediate
5204 
5205   Notes:
5206   The result of this call are the same as if one converted the matrix to dense format
5207   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5208 
5209   This code is only implemented for a couple of matrix formats.
5210 
5211 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5212 @*/
5213 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5214 {
5215   PetscFunctionBegin;
5216   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5217   PetscValidType(mat, 1);
5218   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5219   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5220 
5221   if (!mat->cmap->N) {
5222     PetscCall(VecSet(v, PETSC_MIN_REAL));
5223     if (idx) {
5224       PetscInt i, m = mat->rmap->n;
5225       for (i = 0; i < m; i++) idx[i] = -1;
5226     }
5227   } else {
5228     MatCheckPreallocated(mat, 1);
5229     PetscUseTypeMethod(mat, getrowmax, v, idx);
5230   }
5231   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5232   PetscFunctionReturn(PETSC_SUCCESS);
5233 }
5234 
5235 /*@
5236   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5237   row of the matrix
5238 
5239   Logically Collective
5240 
5241   Input Parameter:
5242 . mat - the matrix
5243 
5244   Output Parameters:
5245 + v   - the vector for storing the maximums
5246 - idx - the indices of the column found for each row (or `NULL` if not needed)
5247 
5248   Level: intermediate
5249 
5250   Notes:
5251   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5252   row is 0 (the first column).
5253 
5254   This code is only implemented for a couple of matrix formats.
5255 
5256 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5257 @*/
5258 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5259 {
5260   PetscFunctionBegin;
5261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5262   PetscValidType(mat, 1);
5263   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5264   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5265 
5266   if (!mat->cmap->N) {
5267     PetscCall(VecSet(v, 0.0));
5268     if (idx) {
5269       PetscInt i, m = mat->rmap->n;
5270       for (i = 0; i < m; i++) idx[i] = -1;
5271     }
5272   } else {
5273     MatCheckPreallocated(mat, 1);
5274     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5275     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5276   }
5277   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5278   PetscFunctionReturn(PETSC_SUCCESS);
5279 }
5280 
5281 /*@
5282   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5283 
5284   Logically Collective
5285 
5286   Input Parameter:
5287 . mat - the matrix
5288 
5289   Output Parameter:
5290 . v - the vector for storing the sum
5291 
5292   Level: intermediate
5293 
5294   This code is only implemented for a couple of matrix formats.
5295 
5296 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5297 @*/
5298 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5299 {
5300   PetscFunctionBegin;
5301   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5302   PetscValidType(mat, 1);
5303   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5304   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5305 
5306   if (!mat->cmap->N) {
5307     PetscCall(VecSet(v, 0.0));
5308   } else {
5309     MatCheckPreallocated(mat, 1);
5310     PetscUseTypeMethod(mat, getrowsumabs, v);
5311   }
5312   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5313   PetscFunctionReturn(PETSC_SUCCESS);
5314 }
5315 
5316 /*@
5317   MatGetRowSum - Gets the sum of each row of the matrix
5318 
5319   Logically or Neighborhood Collective
5320 
5321   Input Parameter:
5322 . mat - the matrix
5323 
5324   Output Parameter:
5325 . v - the vector for storing the sum of rows
5326 
5327   Level: intermediate
5328 
5329   Note:
5330   This code is slow since it is not currently specialized for different formats
5331 
5332 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5333 @*/
5334 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5335 {
5336   Vec ones;
5337 
5338   PetscFunctionBegin;
5339   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5340   PetscValidType(mat, 1);
5341   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5342   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5343   MatCheckPreallocated(mat, 1);
5344   PetscCall(MatCreateVecs(mat, &ones, NULL));
5345   PetscCall(VecSet(ones, 1.));
5346   PetscCall(MatMult(mat, ones, v));
5347   PetscCall(VecDestroy(&ones));
5348   PetscFunctionReturn(PETSC_SUCCESS);
5349 }
5350 
5351 /*@
5352   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5353   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5354 
5355   Collective
5356 
5357   Input Parameter:
5358 . mat - the matrix to provide the transpose
5359 
5360   Output Parameter:
5361 . 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
5362 
5363   Level: advanced
5364 
5365   Note:
5366   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
5367   routine allows bypassing that call.
5368 
5369 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5370 @*/
5371 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5372 {
5373   MatParentState *rb = NULL;
5374 
5375   PetscFunctionBegin;
5376   PetscCall(PetscNew(&rb));
5377   rb->id    = ((PetscObject)mat)->id;
5378   rb->state = 0;
5379   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5380   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5381   PetscFunctionReturn(PETSC_SUCCESS);
5382 }
5383 
5384 /*@
5385   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5386 
5387   Collective
5388 
5389   Input Parameters:
5390 + mat   - the matrix to transpose
5391 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5392 
5393   Output Parameter:
5394 . B - the transpose of the matrix
5395 
5396   Level: intermediate
5397 
5398   Notes:
5399   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5400 
5401   `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
5402   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5403 
5404   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.
5405 
5406   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5407   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5408 
5409   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5410 
5411   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5412 
5413 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5414           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5415 @*/
5416 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5417 {
5418   PetscContainer  rB = NULL;
5419   MatParentState *rb = NULL;
5420 
5421   PetscFunctionBegin;
5422   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5423   PetscValidType(mat, 1);
5424   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5425   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5426   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5427   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5428   MatCheckPreallocated(mat, 1);
5429   if (reuse == MAT_REUSE_MATRIX) {
5430     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5431     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5432     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5433     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5434     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5435   }
5436 
5437   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5438   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5439     PetscUseTypeMethod(mat, transpose, reuse, B);
5440     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5441   }
5442   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5443 
5444   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5445   if (reuse != MAT_INPLACE_MATRIX) {
5446     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5447     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5448     rb->state        = ((PetscObject)mat)->state;
5449     rb->nonzerostate = mat->nonzerostate;
5450   }
5451   PetscFunctionReturn(PETSC_SUCCESS);
5452 }
5453 
5454 /*@
5455   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5456 
5457   Collective
5458 
5459   Input Parameter:
5460 . A - the matrix to transpose
5461 
5462   Output Parameter:
5463 . 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
5464       numerical portion.
5465 
5466   Level: intermediate
5467 
5468   Note:
5469   This is not supported for many matrix types, use `MatTranspose()` in those cases
5470 
5471 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5472 @*/
5473 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5474 {
5475   PetscFunctionBegin;
5476   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5477   PetscValidType(A, 1);
5478   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5479   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5480   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5481   PetscUseTypeMethod(A, transposesymbolic, B);
5482   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5483 
5484   PetscCall(MatTransposeSetPrecursor(A, *B));
5485   PetscFunctionReturn(PETSC_SUCCESS);
5486 }
5487 
5488 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5489 {
5490   PetscContainer  rB;
5491   MatParentState *rb;
5492 
5493   PetscFunctionBegin;
5494   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5495   PetscValidType(A, 1);
5496   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5497   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5498   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5499   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5500   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5501   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5502   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5503   PetscFunctionReturn(PETSC_SUCCESS);
5504 }
5505 
5506 /*@
5507   MatIsTranspose - Test whether a matrix is another one's transpose,
5508   or its own, in which case it tests symmetry.
5509 
5510   Collective
5511 
5512   Input Parameters:
5513 + A   - the matrix to test
5514 . B   - the matrix to test against, this can equal the first parameter
5515 - tol - tolerance, differences between entries smaller than this are counted as zero
5516 
5517   Output Parameter:
5518 . flg - the result
5519 
5520   Level: intermediate
5521 
5522   Notes:
5523   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5524   test involves parallel copies of the block off-diagonal parts of the matrix.
5525 
5526 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5527 @*/
5528 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5529 {
5530   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5531 
5532   PetscFunctionBegin;
5533   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5534   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5535   PetscAssertPointer(flg, 4);
5536   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5537   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5538   *flg = PETSC_FALSE;
5539   if (f && g) {
5540     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5541     PetscCall((*f)(A, B, tol, flg));
5542   } else {
5543     MatType mattype;
5544 
5545     PetscCall(MatGetType(f ? B : A, &mattype));
5546     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5547   }
5548   PetscFunctionReturn(PETSC_SUCCESS);
5549 }
5550 
5551 /*@
5552   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5553 
5554   Collective
5555 
5556   Input Parameters:
5557 + mat   - the matrix to transpose and complex conjugate
5558 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5559 
5560   Output Parameter:
5561 . B - the Hermitian transpose
5562 
5563   Level: intermediate
5564 
5565 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5566 @*/
5567 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5568 {
5569   PetscFunctionBegin;
5570   PetscCall(MatTranspose(mat, reuse, B));
5571 #if defined(PETSC_USE_COMPLEX)
5572   PetscCall(MatConjugate(*B));
5573 #endif
5574   PetscFunctionReturn(PETSC_SUCCESS);
5575 }
5576 
5577 /*@
5578   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5579 
5580   Collective
5581 
5582   Input Parameters:
5583 + A   - the matrix to test
5584 . B   - the matrix to test against, this can equal the first parameter
5585 - tol - tolerance, differences between entries smaller than this are counted as zero
5586 
5587   Output Parameter:
5588 . flg - the result
5589 
5590   Level: intermediate
5591 
5592   Notes:
5593   Only available for `MATAIJ` matrices.
5594 
5595   The sequential algorithm
5596   has a running time of the order of the number of nonzeros; the parallel
5597   test involves parallel copies of the block off-diagonal parts of the matrix.
5598 
5599 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5600 @*/
5601 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5602 {
5603   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5604 
5605   PetscFunctionBegin;
5606   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5607   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5608   PetscAssertPointer(flg, 4);
5609   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5610   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5611   if (f && g) {
5612     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5613     PetscCall((*f)(A, B, tol, flg));
5614   }
5615   PetscFunctionReturn(PETSC_SUCCESS);
5616 }
5617 
5618 /*@
5619   MatPermute - Creates a new matrix with rows and columns permuted from the
5620   original.
5621 
5622   Collective
5623 
5624   Input Parameters:
5625 + mat - the matrix to permute
5626 . row - row permutation, each processor supplies only the permutation for its rows
5627 - col - column permutation, each processor supplies only the permutation for its columns
5628 
5629   Output Parameter:
5630 . B - the permuted matrix
5631 
5632   Level: advanced
5633 
5634   Note:
5635   The index sets map from row/col of permuted matrix to row/col of original matrix.
5636   The index sets should be on the same communicator as mat and have the same local sizes.
5637 
5638   Developer Note:
5639   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5640   exploit the fact that row and col are permutations, consider implementing the
5641   more general `MatCreateSubMatrix()` instead.
5642 
5643 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5644 @*/
5645 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5646 {
5647   PetscFunctionBegin;
5648   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5649   PetscValidType(mat, 1);
5650   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5651   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5652   PetscAssertPointer(B, 4);
5653   PetscCheckSameComm(mat, 1, row, 2);
5654   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5655   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5656   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5657   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5658   MatCheckPreallocated(mat, 1);
5659 
5660   if (mat->ops->permute) {
5661     PetscUseTypeMethod(mat, permute, row, col, B);
5662     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5663   } else {
5664     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5665   }
5666   PetscFunctionReturn(PETSC_SUCCESS);
5667 }
5668 
5669 /*@
5670   MatEqual - Compares two matrices.
5671 
5672   Collective
5673 
5674   Input Parameters:
5675 + A - the first matrix
5676 - B - the second matrix
5677 
5678   Output Parameter:
5679 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5680 
5681   Level: intermediate
5682 
5683 .seealso: [](ch_matrices), `Mat`
5684 @*/
5685 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5686 {
5687   PetscFunctionBegin;
5688   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5689   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5690   PetscValidType(A, 1);
5691   PetscValidType(B, 2);
5692   PetscAssertPointer(flg, 3);
5693   PetscCheckSameComm(A, 1, B, 2);
5694   MatCheckPreallocated(A, 1);
5695   MatCheckPreallocated(B, 2);
5696   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5697   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5698   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,
5699              B->cmap->N);
5700   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5701     PetscUseTypeMethod(A, equal, B, flg);
5702   } else {
5703     PetscCall(MatMultEqual(A, B, 10, flg));
5704   }
5705   PetscFunctionReturn(PETSC_SUCCESS);
5706 }
5707 
5708 /*@
5709   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5710   matrices that are stored as vectors.  Either of the two scaling
5711   matrices can be `NULL`.
5712 
5713   Collective
5714 
5715   Input Parameters:
5716 + mat - the matrix to be scaled
5717 . l   - the left scaling vector (or `NULL`)
5718 - r   - the right scaling vector (or `NULL`)
5719 
5720   Level: intermediate
5721 
5722   Note:
5723   `MatDiagonalScale()` computes $A = LAR$, where
5724   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5725   The L scales the rows of the matrix, the R scales the columns of the matrix.
5726 
5727 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5728 @*/
5729 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5730 {
5731   PetscFunctionBegin;
5732   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5733   PetscValidType(mat, 1);
5734   if (l) {
5735     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5736     PetscCheckSameComm(mat, 1, l, 2);
5737   }
5738   if (r) {
5739     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5740     PetscCheckSameComm(mat, 1, r, 3);
5741   }
5742   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5743   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5744   MatCheckPreallocated(mat, 1);
5745   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5746 
5747   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5748   PetscUseTypeMethod(mat, diagonalscale, l, r);
5749   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5750   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5751   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5752   PetscFunctionReturn(PETSC_SUCCESS);
5753 }
5754 
5755 /*@
5756   MatScale - Scales all elements of a matrix by a given number.
5757 
5758   Logically Collective
5759 
5760   Input Parameters:
5761 + mat - the matrix to be scaled
5762 - a   - the scaling value
5763 
5764   Level: intermediate
5765 
5766 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5767 @*/
5768 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5769 {
5770   PetscFunctionBegin;
5771   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5772   PetscValidType(mat, 1);
5773   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5774   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5775   PetscValidLogicalCollectiveScalar(mat, a, 2);
5776   MatCheckPreallocated(mat, 1);
5777 
5778   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5779   if (a != (PetscScalar)1.0) {
5780     PetscUseTypeMethod(mat, scale, a);
5781     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5782   }
5783   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5784   PetscFunctionReturn(PETSC_SUCCESS);
5785 }
5786 
5787 /*@
5788   MatNorm - Calculates various norms of a matrix.
5789 
5790   Collective
5791 
5792   Input Parameters:
5793 + mat  - the matrix
5794 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5795 
5796   Output Parameter:
5797 . nrm - the resulting norm
5798 
5799   Level: intermediate
5800 
5801 .seealso: [](ch_matrices), `Mat`
5802 @*/
5803 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5804 {
5805   PetscFunctionBegin;
5806   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5807   PetscValidType(mat, 1);
5808   PetscAssertPointer(nrm, 3);
5809 
5810   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5811   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5812   MatCheckPreallocated(mat, 1);
5813 
5814   PetscUseTypeMethod(mat, norm, type, nrm);
5815   PetscFunctionReturn(PETSC_SUCCESS);
5816 }
5817 
5818 /*
5819      This variable is used to prevent counting of MatAssemblyBegin() that
5820    are called from within a MatAssemblyEnd().
5821 */
5822 static PetscInt MatAssemblyEnd_InUse = 0;
5823 /*@
5824   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5825   be called after completing all calls to `MatSetValues()`.
5826 
5827   Collective
5828 
5829   Input Parameters:
5830 + mat  - the matrix
5831 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5832 
5833   Level: beginner
5834 
5835   Notes:
5836   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5837   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5838 
5839   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5840   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5841   using the matrix.
5842 
5843   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5844   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
5845   a global collective operation requiring all processes that share the matrix.
5846 
5847   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5848   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5849   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5850 
5851 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5852 @*/
5853 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5854 {
5855   PetscFunctionBegin;
5856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5857   PetscValidType(mat, 1);
5858   MatCheckPreallocated(mat, 1);
5859   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5860   if (mat->assembled) {
5861     mat->was_assembled = PETSC_TRUE;
5862     mat->assembled     = PETSC_FALSE;
5863   }
5864 
5865   if (!MatAssemblyEnd_InUse) {
5866     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5867     PetscTryTypeMethod(mat, assemblybegin, type);
5868     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5869   } else PetscTryTypeMethod(mat, assemblybegin, type);
5870   PetscFunctionReturn(PETSC_SUCCESS);
5871 }
5872 
5873 /*@
5874   MatAssembled - Indicates if a matrix has been assembled and is ready for
5875   use; for example, in matrix-vector product.
5876 
5877   Not Collective
5878 
5879   Input Parameter:
5880 . mat - the matrix
5881 
5882   Output Parameter:
5883 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5884 
5885   Level: advanced
5886 
5887 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5888 @*/
5889 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5890 {
5891   PetscFunctionBegin;
5892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5893   PetscAssertPointer(assembled, 2);
5894   *assembled = mat->assembled;
5895   PetscFunctionReturn(PETSC_SUCCESS);
5896 }
5897 
5898 /*@
5899   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5900   be called after `MatAssemblyBegin()`.
5901 
5902   Collective
5903 
5904   Input Parameters:
5905 + mat  - the matrix
5906 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5907 
5908   Options Database Keys:
5909 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5910 . -mat_view ::ascii_info_detail      - Prints more detailed info
5911 . -mat_view                          - Prints matrix in ASCII format
5912 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5913 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5914 . -display <name>                    - Sets display name (default is host)
5915 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5916 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5917 . -viewer_socket_machine <machine>   - Machine to use for socket
5918 . -viewer_socket_port <port>         - Port number to use for socket
5919 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5920 
5921   Level: beginner
5922 
5923 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5924 @*/
5925 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5926 {
5927   static PetscInt inassm = 0;
5928   PetscBool       flg    = PETSC_FALSE;
5929 
5930   PetscFunctionBegin;
5931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5932   PetscValidType(mat, 1);
5933 
5934   inassm++;
5935   MatAssemblyEnd_InUse++;
5936   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5937     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5938     PetscTryTypeMethod(mat, assemblyend, type);
5939     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5940   } else PetscTryTypeMethod(mat, assemblyend, type);
5941 
5942   /* Flush assembly is not a true assembly */
5943   if (type != MAT_FLUSH_ASSEMBLY) {
5944     if (mat->num_ass) {
5945       if (!mat->symmetry_eternal) {
5946         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5947         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5948       }
5949       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5950       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5951     }
5952     mat->num_ass++;
5953     mat->assembled        = PETSC_TRUE;
5954     mat->ass_nonzerostate = mat->nonzerostate;
5955   }
5956 
5957   mat->insertmode = NOT_SET_VALUES;
5958   MatAssemblyEnd_InUse--;
5959   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5960   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5961     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5962 
5963     if (mat->checksymmetryonassembly) {
5964       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5965       if (flg) {
5966         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5967       } else {
5968         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5969       }
5970     }
5971     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5972   }
5973   inassm--;
5974   PetscFunctionReturn(PETSC_SUCCESS);
5975 }
5976 
5977 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5978 /*@
5979   MatSetOption - Sets a parameter option for a matrix. Some options
5980   may be specific to certain storage formats.  Some options
5981   determine how values will be inserted (or added). Sorted,
5982   row-oriented input will generally assemble the fastest. The default
5983   is row-oriented.
5984 
5985   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5986 
5987   Input Parameters:
5988 + mat - the matrix
5989 . op  - the option, one of those listed below (and possibly others),
5990 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5991 
5992   Options Describing Matrix Structure:
5993 + `MAT_SPD`                         - symmetric positive definite
5994 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5995 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5996 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5997 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5998 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5999 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
6000 
6001    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
6002    do not need to be computed (usually at a high cost)
6003 
6004    Options For Use with `MatSetValues()`:
6005    Insert a logically dense subblock, which can be
6006 . `MAT_ROW_ORIENTED`                - row-oriented (default)
6007 
6008    These options reflect the data you pass in with `MatSetValues()`; it has
6009    nothing to do with how the data is stored internally in the matrix
6010    data structure.
6011 
6012    When (re)assembling a matrix, we can restrict the input for
6013    efficiency/debugging purposes.  These options include
6014 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
6015 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
6016 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
6017 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
6018 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
6019 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
6020         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
6021         performance for very large process counts.
6022 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
6023         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
6024         functions, instead sending only neighbor messages.
6025 
6026   Level: intermediate
6027 
6028   Notes:
6029   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
6030 
6031   Some options are relevant only for particular matrix types and
6032   are thus ignored by others.  Other options are not supported by
6033   certain matrix types and will generate an error message if set.
6034 
6035   If using Fortran to compute a matrix, one may need to
6036   use the column-oriented option (or convert to the row-oriented
6037   format).
6038 
6039   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
6040   that would generate a new entry in the nonzero structure is instead
6041   ignored.  Thus, if memory has not already been allocated for this particular
6042   data, then the insertion is ignored. For dense matrices, in which
6043   the entire array is allocated, no entries are ever ignored.
6044   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6045 
6046   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6047   that would generate a new entry in the nonzero structure instead produces
6048   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
6049 
6050   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6051   that would generate a new entry that has not been preallocated will
6052   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6053   only.) This is a useful flag when debugging matrix memory preallocation.
6054   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6055 
6056   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6057   other processors should be dropped, rather than stashed.
6058   This is useful if you know that the "owning" processor is also
6059   always generating the correct matrix entries, so that PETSc need
6060   not transfer duplicate entries generated on another processor.
6061 
6062   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6063   searches during matrix assembly. When this flag is set, the hash table
6064   is created during the first matrix assembly. This hash table is
6065   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6066   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6067   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6068   supported by `MATMPIBAIJ` format only.
6069 
6070   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6071   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6072 
6073   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6074   a zero location in the matrix
6075 
6076   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6077 
6078   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6079   zero row routines and thus improves performance for very large process counts.
6080 
6081   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6082   part of the matrix (since they should match the upper triangular part).
6083 
6084   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6085   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6086   with finite difference schemes with non-periodic boundary conditions.
6087 
6088   Developer Note:
6089   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6090   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6091   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6092   not changed.
6093 
6094 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6095 @*/
6096 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6097 {
6098   PetscFunctionBegin;
6099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6100   if (op > 0) {
6101     PetscValidLogicalCollectiveEnum(mat, op, 2);
6102     PetscValidLogicalCollectiveBool(mat, flg, 3);
6103   }
6104 
6105   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);
6106 
6107   switch (op) {
6108   case MAT_FORCE_DIAGONAL_ENTRIES:
6109     mat->force_diagonals = flg;
6110     PetscFunctionReturn(PETSC_SUCCESS);
6111   case MAT_NO_OFF_PROC_ENTRIES:
6112     mat->nooffprocentries = flg;
6113     PetscFunctionReturn(PETSC_SUCCESS);
6114   case MAT_SUBSET_OFF_PROC_ENTRIES:
6115     mat->assembly_subset = flg;
6116     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6117 #if !defined(PETSC_HAVE_MPIUNI)
6118       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6119 #endif
6120       mat->stash.first_assembly_done = PETSC_FALSE;
6121     }
6122     PetscFunctionReturn(PETSC_SUCCESS);
6123   case MAT_NO_OFF_PROC_ZERO_ROWS:
6124     mat->nooffproczerorows = flg;
6125     PetscFunctionReturn(PETSC_SUCCESS);
6126   case MAT_SPD:
6127     if (flg) {
6128       mat->spd                    = PETSC_BOOL3_TRUE;
6129       mat->symmetric              = PETSC_BOOL3_TRUE;
6130       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6131     } else {
6132       mat->spd = PETSC_BOOL3_FALSE;
6133     }
6134     break;
6135   case MAT_SYMMETRIC:
6136     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6137     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6138 #if !defined(PETSC_USE_COMPLEX)
6139     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6140 #endif
6141     break;
6142   case MAT_HERMITIAN:
6143     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6144     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6145 #if !defined(PETSC_USE_COMPLEX)
6146     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6147 #endif
6148     break;
6149   case MAT_STRUCTURALLY_SYMMETRIC:
6150     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6151     break;
6152   case MAT_SYMMETRY_ETERNAL:
6153     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");
6154     mat->symmetry_eternal = flg;
6155     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6156     break;
6157   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6158     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");
6159     mat->structural_symmetry_eternal = flg;
6160     break;
6161   case MAT_SPD_ETERNAL:
6162     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");
6163     mat->spd_eternal = flg;
6164     if (flg) {
6165       mat->structural_symmetry_eternal = PETSC_TRUE;
6166       mat->symmetry_eternal            = PETSC_TRUE;
6167     }
6168     break;
6169   case MAT_STRUCTURE_ONLY:
6170     mat->structure_only = flg;
6171     break;
6172   case MAT_SORTED_FULL:
6173     mat->sortedfull = flg;
6174     break;
6175   default:
6176     break;
6177   }
6178   PetscTryTypeMethod(mat, setoption, op, flg);
6179   PetscFunctionReturn(PETSC_SUCCESS);
6180 }
6181 
6182 /*@
6183   MatGetOption - Gets a parameter option that has been set for a matrix.
6184 
6185   Logically Collective
6186 
6187   Input Parameters:
6188 + mat - the matrix
6189 - op  - the option, this only responds to certain options, check the code for which ones
6190 
6191   Output Parameter:
6192 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6193 
6194   Level: intermediate
6195 
6196   Notes:
6197   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6198 
6199   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6200   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6201 
6202 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6203     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6204 @*/
6205 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6206 {
6207   PetscFunctionBegin;
6208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6209   PetscValidType(mat, 1);
6210 
6211   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);
6212   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()");
6213 
6214   switch (op) {
6215   case MAT_NO_OFF_PROC_ENTRIES:
6216     *flg = mat->nooffprocentries;
6217     break;
6218   case MAT_NO_OFF_PROC_ZERO_ROWS:
6219     *flg = mat->nooffproczerorows;
6220     break;
6221   case MAT_SYMMETRIC:
6222     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6223     break;
6224   case MAT_HERMITIAN:
6225     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6226     break;
6227   case MAT_STRUCTURALLY_SYMMETRIC:
6228     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6229     break;
6230   case MAT_SPD:
6231     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6232     break;
6233   case MAT_SYMMETRY_ETERNAL:
6234     *flg = mat->symmetry_eternal;
6235     break;
6236   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6237     *flg = mat->symmetry_eternal;
6238     break;
6239   default:
6240     break;
6241   }
6242   PetscFunctionReturn(PETSC_SUCCESS);
6243 }
6244 
6245 /*@
6246   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6247   this routine retains the old nonzero structure.
6248 
6249   Logically Collective
6250 
6251   Input Parameter:
6252 . mat - the matrix
6253 
6254   Level: intermediate
6255 
6256   Note:
6257   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.
6258   See the Performance chapter of the users manual for information on preallocating matrices.
6259 
6260 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6261 @*/
6262 PetscErrorCode MatZeroEntries(Mat mat)
6263 {
6264   PetscFunctionBegin;
6265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6266   PetscValidType(mat, 1);
6267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6268   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");
6269   MatCheckPreallocated(mat, 1);
6270 
6271   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6272   PetscUseTypeMethod(mat, zeroentries);
6273   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6274   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6275   PetscFunctionReturn(PETSC_SUCCESS);
6276 }
6277 
6278 /*@
6279   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6280   of a set of rows and columns of a matrix.
6281 
6282   Collective
6283 
6284   Input Parameters:
6285 + mat     - the matrix
6286 . numRows - the number of rows/columns to zero
6287 . rows    - the global row indices
6288 . diag    - value put in the diagonal of the eliminated rows
6289 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6290 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6291 
6292   Level: intermediate
6293 
6294   Notes:
6295   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6296 
6297   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6298   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
6299 
6300   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6301   Krylov method to take advantage of the known solution on the zeroed rows.
6302 
6303   For the parallel case, all processes that share the matrix (i.e.,
6304   those in the communicator used for matrix creation) MUST call this
6305   routine, regardless of whether any rows being zeroed are owned by
6306   them.
6307 
6308   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6309   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
6310   missing.
6311 
6312   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6313   list only rows local to itself).
6314 
6315   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6316 
6317 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6318           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6319 @*/
6320 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6321 {
6322   PetscFunctionBegin;
6323   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6324   PetscValidType(mat, 1);
6325   if (numRows) PetscAssertPointer(rows, 3);
6326   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6327   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6328   MatCheckPreallocated(mat, 1);
6329 
6330   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6331   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6332   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6333   PetscFunctionReturn(PETSC_SUCCESS);
6334 }
6335 
6336 /*@
6337   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6338   of a set of rows and columns of a matrix.
6339 
6340   Collective
6341 
6342   Input Parameters:
6343 + mat  - the matrix
6344 . is   - the rows to zero
6345 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6346 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6347 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6348 
6349   Level: intermediate
6350 
6351   Note:
6352   See `MatZeroRowsColumns()` for details on how this routine operates.
6353 
6354 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6355           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6356 @*/
6357 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6358 {
6359   PetscInt        numRows;
6360   const PetscInt *rows;
6361 
6362   PetscFunctionBegin;
6363   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6364   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6365   PetscValidType(mat, 1);
6366   PetscValidType(is, 2);
6367   PetscCall(ISGetLocalSize(is, &numRows));
6368   PetscCall(ISGetIndices(is, &rows));
6369   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6370   PetscCall(ISRestoreIndices(is, &rows));
6371   PetscFunctionReturn(PETSC_SUCCESS);
6372 }
6373 
6374 /*@
6375   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6376   of a set of rows of a matrix.
6377 
6378   Collective
6379 
6380   Input Parameters:
6381 + mat     - the matrix
6382 . numRows - the number of rows to zero
6383 . rows    - the global row indices
6384 . diag    - value put in the diagonal of the zeroed rows
6385 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6386 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6387 
6388   Level: intermediate
6389 
6390   Notes:
6391   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6392 
6393   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6394 
6395   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6396   Krylov method to take advantage of the known solution on the zeroed rows.
6397 
6398   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)
6399   from the matrix.
6400 
6401   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6402   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6403   formats this does not alter the nonzero structure.
6404 
6405   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6406   of the matrix is not changed the values are
6407   merely zeroed.
6408 
6409   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6410   formats can optionally remove the main diagonal entry from the
6411   nonzero structure as well, by passing 0.0 as the final argument).
6412 
6413   For the parallel case, all processes that share the matrix (i.e.,
6414   those in the communicator used for matrix creation) MUST call this
6415   routine, regardless of whether any rows being zeroed are owned by
6416   them.
6417 
6418   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6419   list only rows local to itself).
6420 
6421   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6422   owns that are to be zeroed. This saves a global synchronization in the implementation.
6423 
6424 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6425           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6426 @*/
6427 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6428 {
6429   PetscFunctionBegin;
6430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6431   PetscValidType(mat, 1);
6432   if (numRows) PetscAssertPointer(rows, 3);
6433   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6434   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6435   MatCheckPreallocated(mat, 1);
6436 
6437   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6438   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6439   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6440   PetscFunctionReturn(PETSC_SUCCESS);
6441 }
6442 
6443 /*@
6444   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6445   of a set of rows of a matrix indicated by an `IS`
6446 
6447   Collective
6448 
6449   Input Parameters:
6450 + mat  - the matrix
6451 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6452 . diag - value put in all diagonals of eliminated rows
6453 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6454 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6455 
6456   Level: intermediate
6457 
6458   Note:
6459   See `MatZeroRows()` for details on how this routine operates.
6460 
6461 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6462           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6463 @*/
6464 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6465 {
6466   PetscInt        numRows = 0;
6467   const PetscInt *rows    = NULL;
6468 
6469   PetscFunctionBegin;
6470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6471   PetscValidType(mat, 1);
6472   if (is) {
6473     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6474     PetscCall(ISGetLocalSize(is, &numRows));
6475     PetscCall(ISGetIndices(is, &rows));
6476   }
6477   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6478   if (is) PetscCall(ISRestoreIndices(is, &rows));
6479   PetscFunctionReturn(PETSC_SUCCESS);
6480 }
6481 
6482 /*@
6483   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6484   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6485 
6486   Collective
6487 
6488   Input Parameters:
6489 + mat     - the matrix
6490 . numRows - the number of rows to remove
6491 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6492 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6493 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6494 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6495 
6496   Level: intermediate
6497 
6498   Notes:
6499   See `MatZeroRows()` for details on how this routine operates.
6500 
6501   The grid coordinates are across the entire grid, not just the local portion
6502 
6503   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6504   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6505   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6506   `DM_BOUNDARY_PERIODIC` boundary type.
6507 
6508   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
6509   a single value per point) you can skip filling those indices.
6510 
6511   Fortran Note:
6512   `idxm` and `idxn` should be declared as
6513 $     MatStencil idxm(4, m)
6514   and the values inserted using
6515 .vb
6516     idxm(MatStencil_i, 1) = i
6517     idxm(MatStencil_j, 1) = j
6518     idxm(MatStencil_k, 1) = k
6519     idxm(MatStencil_c, 1) = c
6520    etc
6521 .ve
6522 
6523 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6524           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6525 @*/
6526 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6527 {
6528   PetscInt  dim    = mat->stencil.dim;
6529   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6530   PetscInt *dims   = mat->stencil.dims + 1;
6531   PetscInt *starts = mat->stencil.starts;
6532   PetscInt *dxm    = (PetscInt *)rows;
6533   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6534 
6535   PetscFunctionBegin;
6536   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6537   PetscValidType(mat, 1);
6538   if (numRows) PetscAssertPointer(rows, 3);
6539 
6540   PetscCall(PetscMalloc1(numRows, &jdxm));
6541   for (i = 0; i < numRows; ++i) {
6542     /* Skip unused dimensions (they are ordered k, j, i, c) */
6543     for (j = 0; j < 3 - sdim; ++j) dxm++;
6544     /* Local index in X dir */
6545     tmp = *dxm++ - starts[0];
6546     /* Loop over remaining dimensions */
6547     for (j = 0; j < dim - 1; ++j) {
6548       /* If nonlocal, set index to be negative */
6549       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6550       /* Update local index */
6551       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6552     }
6553     /* Skip component slot if necessary */
6554     if (mat->stencil.noc) dxm++;
6555     /* Local row number */
6556     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6557   }
6558   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6559   PetscCall(PetscFree(jdxm));
6560   PetscFunctionReturn(PETSC_SUCCESS);
6561 }
6562 
6563 /*@
6564   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6565   of a set of rows and columns of a matrix.
6566 
6567   Collective
6568 
6569   Input Parameters:
6570 + mat     - the matrix
6571 . numRows - the number of rows/columns to remove
6572 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6573 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6574 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6575 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6576 
6577   Level: intermediate
6578 
6579   Notes:
6580   See `MatZeroRowsColumns()` for details on how this routine operates.
6581 
6582   The grid coordinates are across the entire grid, not just the local portion
6583 
6584   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6585   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6586   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6587   `DM_BOUNDARY_PERIODIC` boundary type.
6588 
6589   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
6590   a single value per point) you can skip filling those indices.
6591 
6592   Fortran Note:
6593   `idxm` and `idxn` should be declared as
6594 $     MatStencil idxm(4, m)
6595   and the values inserted using
6596 .vb
6597     idxm(MatStencil_i, 1) = i
6598     idxm(MatStencil_j, 1) = j
6599     idxm(MatStencil_k, 1) = k
6600     idxm(MatStencil_c, 1) = c
6601     etc
6602 .ve
6603 
6604 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6605           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6606 @*/
6607 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6608 {
6609   PetscInt  dim    = mat->stencil.dim;
6610   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6611   PetscInt *dims   = mat->stencil.dims + 1;
6612   PetscInt *starts = mat->stencil.starts;
6613   PetscInt *dxm    = (PetscInt *)rows;
6614   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6615 
6616   PetscFunctionBegin;
6617   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6618   PetscValidType(mat, 1);
6619   if (numRows) PetscAssertPointer(rows, 3);
6620 
6621   PetscCall(PetscMalloc1(numRows, &jdxm));
6622   for (i = 0; i < numRows; ++i) {
6623     /* Skip unused dimensions (they are ordered k, j, i, c) */
6624     for (j = 0; j < 3 - sdim; ++j) dxm++;
6625     /* Local index in X dir */
6626     tmp = *dxm++ - starts[0];
6627     /* Loop over remaining dimensions */
6628     for (j = 0; j < dim - 1; ++j) {
6629       /* If nonlocal, set index to be negative */
6630       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6631       /* Update local index */
6632       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6633     }
6634     /* Skip component slot if necessary */
6635     if (mat->stencil.noc) dxm++;
6636     /* Local row number */
6637     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6638   }
6639   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6640   PetscCall(PetscFree(jdxm));
6641   PetscFunctionReturn(PETSC_SUCCESS);
6642 }
6643 
6644 /*@
6645   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6646   of a set of rows of a matrix; using local numbering of rows.
6647 
6648   Collective
6649 
6650   Input Parameters:
6651 + mat     - the matrix
6652 . numRows - the number of rows to remove
6653 . rows    - the local row indices
6654 . diag    - value put in all diagonals of eliminated rows
6655 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6656 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6657 
6658   Level: intermediate
6659 
6660   Notes:
6661   Before calling `MatZeroRowsLocal()`, the user must first set the
6662   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6663 
6664   See `MatZeroRows()` for details on how this routine operates.
6665 
6666 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6667           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6668 @*/
6669 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6670 {
6671   PetscFunctionBegin;
6672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6673   PetscValidType(mat, 1);
6674   if (numRows) PetscAssertPointer(rows, 3);
6675   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6676   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6677   MatCheckPreallocated(mat, 1);
6678 
6679   if (mat->ops->zerorowslocal) {
6680     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6681   } else {
6682     IS              is, newis;
6683     const PetscInt *newRows;
6684 
6685     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6686     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6687     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6688     PetscCall(ISGetIndices(newis, &newRows));
6689     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6690     PetscCall(ISRestoreIndices(newis, &newRows));
6691     PetscCall(ISDestroy(&newis));
6692     PetscCall(ISDestroy(&is));
6693   }
6694   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6695   PetscFunctionReturn(PETSC_SUCCESS);
6696 }
6697 
6698 /*@
6699   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6700   of a set of rows of a matrix; using local numbering of rows.
6701 
6702   Collective
6703 
6704   Input Parameters:
6705 + mat  - the matrix
6706 . is   - index set of rows to remove
6707 . diag - value put in all diagonals of eliminated rows
6708 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6709 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6710 
6711   Level: intermediate
6712 
6713   Notes:
6714   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6715   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6716 
6717   See `MatZeroRows()` for details on how this routine operates.
6718 
6719 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6720           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6721 @*/
6722 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6723 {
6724   PetscInt        numRows;
6725   const PetscInt *rows;
6726 
6727   PetscFunctionBegin;
6728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6729   PetscValidType(mat, 1);
6730   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6731   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6732   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6733   MatCheckPreallocated(mat, 1);
6734 
6735   PetscCall(ISGetLocalSize(is, &numRows));
6736   PetscCall(ISGetIndices(is, &rows));
6737   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6738   PetscCall(ISRestoreIndices(is, &rows));
6739   PetscFunctionReturn(PETSC_SUCCESS);
6740 }
6741 
6742 /*@
6743   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6744   of a set of rows and columns of a matrix; using local numbering of rows.
6745 
6746   Collective
6747 
6748   Input Parameters:
6749 + mat     - the matrix
6750 . numRows - the number of rows to remove
6751 . rows    - the global row indices
6752 . diag    - value put in all diagonals of eliminated rows
6753 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6754 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6755 
6756   Level: intermediate
6757 
6758   Notes:
6759   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6760   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6761 
6762   See `MatZeroRowsColumns()` for details on how this routine operates.
6763 
6764 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6765           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6766 @*/
6767 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6768 {
6769   IS              is, newis;
6770   const PetscInt *newRows;
6771 
6772   PetscFunctionBegin;
6773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6774   PetscValidType(mat, 1);
6775   if (numRows) PetscAssertPointer(rows, 3);
6776   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6777   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6778   MatCheckPreallocated(mat, 1);
6779 
6780   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6781   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6782   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6783   PetscCall(ISGetIndices(newis, &newRows));
6784   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6785   PetscCall(ISRestoreIndices(newis, &newRows));
6786   PetscCall(ISDestroy(&newis));
6787   PetscCall(ISDestroy(&is));
6788   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6789   PetscFunctionReturn(PETSC_SUCCESS);
6790 }
6791 
6792 /*@
6793   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6794   of a set of rows and columns of a matrix; using local numbering of rows.
6795 
6796   Collective
6797 
6798   Input Parameters:
6799 + mat  - the matrix
6800 . is   - index set of rows to remove
6801 . diag - value put in all diagonals of eliminated rows
6802 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6803 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6804 
6805   Level: intermediate
6806 
6807   Notes:
6808   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6809   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6810 
6811   See `MatZeroRowsColumns()` for details on how this routine operates.
6812 
6813 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6814           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6815 @*/
6816 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6817 {
6818   PetscInt        numRows;
6819   const PetscInt *rows;
6820 
6821   PetscFunctionBegin;
6822   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6823   PetscValidType(mat, 1);
6824   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6825   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6826   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6827   MatCheckPreallocated(mat, 1);
6828 
6829   PetscCall(ISGetLocalSize(is, &numRows));
6830   PetscCall(ISGetIndices(is, &rows));
6831   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6832   PetscCall(ISRestoreIndices(is, &rows));
6833   PetscFunctionReturn(PETSC_SUCCESS);
6834 }
6835 
6836 /*@
6837   MatGetSize - Returns the numbers of rows and columns in a matrix.
6838 
6839   Not Collective
6840 
6841   Input Parameter:
6842 . mat - the matrix
6843 
6844   Output Parameters:
6845 + m - the number of global rows
6846 - n - the number of global columns
6847 
6848   Level: beginner
6849 
6850   Note:
6851   Both output parameters can be `NULL` on input.
6852 
6853 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6854 @*/
6855 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6856 {
6857   PetscFunctionBegin;
6858   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6859   if (m) *m = mat->rmap->N;
6860   if (n) *n = mat->cmap->N;
6861   PetscFunctionReturn(PETSC_SUCCESS);
6862 }
6863 
6864 /*@
6865   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6866   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6867 
6868   Not Collective
6869 
6870   Input Parameter:
6871 . mat - the matrix
6872 
6873   Output Parameters:
6874 + m - the number of local rows, use `NULL` to not obtain this value
6875 - n - the number of local columns, use `NULL` to not obtain this value
6876 
6877   Level: beginner
6878 
6879 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6880 @*/
6881 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6882 {
6883   PetscFunctionBegin;
6884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6885   if (m) PetscAssertPointer(m, 2);
6886   if (n) PetscAssertPointer(n, 3);
6887   if (m) *m = mat->rmap->n;
6888   if (n) *n = mat->cmap->n;
6889   PetscFunctionReturn(PETSC_SUCCESS);
6890 }
6891 
6892 /*@
6893   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6894   vector one multiplies this matrix by that are owned by this processor.
6895 
6896   Not Collective, unless matrix has not been allocated, then collective
6897 
6898   Input Parameter:
6899 . mat - the matrix
6900 
6901   Output Parameters:
6902 + m - the global index of the first local column, use `NULL` to not obtain this value
6903 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6904 
6905   Level: developer
6906 
6907   Notes:
6908   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6909 
6910   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6911   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6912 
6913   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6914   the local values in the matrix.
6915 
6916   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6917   Layouts](sec_matlayout) for details on matrix layouts.
6918 
6919 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6920           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6921 @*/
6922 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6923 {
6924   PetscFunctionBegin;
6925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6926   PetscValidType(mat, 1);
6927   if (m) PetscAssertPointer(m, 2);
6928   if (n) PetscAssertPointer(n, 3);
6929   MatCheckPreallocated(mat, 1);
6930   if (m) *m = mat->cmap->rstart;
6931   if (n) *n = mat->cmap->rend;
6932   PetscFunctionReturn(PETSC_SUCCESS);
6933 }
6934 
6935 /*@
6936   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6937   this MPI process.
6938 
6939   Not Collective
6940 
6941   Input Parameter:
6942 . mat - the matrix
6943 
6944   Output Parameters:
6945 + m - the global index of the first local row, use `NULL` to not obtain this value
6946 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6947 
6948   Level: beginner
6949 
6950   Notes:
6951   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6952 
6953   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6954   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6955 
6956   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6957   the local values in the matrix.
6958 
6959   The high argument is one more than the last element stored locally.
6960 
6961   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6962   would contain the result of a matrix vector product with this matrix. See [Matrix
6963   Layouts](sec_matlayout) for details on matrix layouts.
6964 
6965 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6966           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6967 @*/
6968 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6969 {
6970   PetscFunctionBegin;
6971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6972   PetscValidType(mat, 1);
6973   if (m) PetscAssertPointer(m, 2);
6974   if (n) PetscAssertPointer(n, 3);
6975   MatCheckPreallocated(mat, 1);
6976   if (m) *m = mat->rmap->rstart;
6977   if (n) *n = mat->rmap->rend;
6978   PetscFunctionReturn(PETSC_SUCCESS);
6979 }
6980 
6981 /*@C
6982   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6983   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6984 
6985   Not Collective, unless matrix has not been allocated
6986 
6987   Input Parameter:
6988 . mat - the matrix
6989 
6990   Output Parameter:
6991 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6992            where `size` is the number of MPI processes used by `mat`
6993 
6994   Level: beginner
6995 
6996   Notes:
6997   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6998 
6999   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7000   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7001 
7002   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7003   the local values in the matrix.
7004 
7005   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
7006   would contain the result of a matrix vector product with this matrix. See [Matrix
7007   Layouts](sec_matlayout) for details on matrix layouts.
7008 
7009 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
7010           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
7011           `DMDAGetGhostCorners()`, `DM`
7012 @*/
7013 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
7014 {
7015   PetscFunctionBegin;
7016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7017   PetscValidType(mat, 1);
7018   MatCheckPreallocated(mat, 1);
7019   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
7020   PetscFunctionReturn(PETSC_SUCCESS);
7021 }
7022 
7023 /*@C
7024   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
7025   vector one multiplies this vector by that are owned by each processor.
7026 
7027   Not Collective, unless matrix has not been allocated
7028 
7029   Input Parameter:
7030 . mat - the matrix
7031 
7032   Output Parameter:
7033 . ranges - start of each processors portion plus one more than the total length at the end
7034 
7035   Level: beginner
7036 
7037   Notes:
7038   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
7039 
7040   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7041   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7042 
7043   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7044   the local values in the matrix.
7045 
7046   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7047   Layouts](sec_matlayout) for details on matrix layouts.
7048 
7049 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7050           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7051           `DMDAGetGhostCorners()`, `DM`
7052 @*/
7053 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7054 {
7055   PetscFunctionBegin;
7056   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7057   PetscValidType(mat, 1);
7058   MatCheckPreallocated(mat, 1);
7059   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7060   PetscFunctionReturn(PETSC_SUCCESS);
7061 }
7062 
7063 /*@
7064   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7065 
7066   Not Collective
7067 
7068   Input Parameter:
7069 . A - matrix
7070 
7071   Output Parameters:
7072 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7073 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7074 
7075   Level: intermediate
7076 
7077   Note:
7078   You should call `ISDestroy()` on the returned `IS`
7079 
7080   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7081   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7082   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7083   details on matrix layouts.
7084 
7085 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7086 @*/
7087 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7088 {
7089   PetscErrorCode (*f)(Mat, IS *, IS *);
7090 
7091   PetscFunctionBegin;
7092   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7093   PetscValidType(A, 1);
7094   MatCheckPreallocated(A, 1);
7095   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7096   if (f) {
7097     PetscCall((*f)(A, rows, cols));
7098   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7099     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7100     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7101   }
7102   PetscFunctionReturn(PETSC_SUCCESS);
7103 }
7104 
7105 /*@
7106   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7107   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7108   to complete the factorization.
7109 
7110   Collective
7111 
7112   Input Parameters:
7113 + fact - the factorized matrix obtained with `MatGetFactor()`
7114 . mat  - the matrix
7115 . row  - row permutation
7116 . col  - column permutation
7117 - info - structure containing
7118 .vb
7119       levels - number of levels of fill.
7120       expected fill - as ratio of original fill.
7121       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7122                 missing diagonal entries)
7123 .ve
7124 
7125   Level: developer
7126 
7127   Notes:
7128   See [Matrix Factorization](sec_matfactor) for additional information.
7129 
7130   Most users should employ the `KSP` interface for linear solvers
7131   instead of working directly with matrix algebra routines such as this.
7132   See, e.g., `KSPCreate()`.
7133 
7134   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7135 
7136   Developer Note:
7137   The Fortran interface is not autogenerated as the
7138   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7139 
7140 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7141           `MatGetOrdering()`, `MatFactorInfo`
7142 @*/
7143 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7144 {
7145   PetscFunctionBegin;
7146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7147   PetscValidType(mat, 2);
7148   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7149   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7150   PetscAssertPointer(info, 5);
7151   PetscAssertPointer(fact, 1);
7152   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7153   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7154   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7155   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7156   MatCheckPreallocated(mat, 2);
7157 
7158   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7159   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7160   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7161   PetscFunctionReturn(PETSC_SUCCESS);
7162 }
7163 
7164 /*@
7165   MatICCFactorSymbolic - Performs symbolic incomplete
7166   Cholesky factorization for a symmetric matrix.  Use
7167   `MatCholeskyFactorNumeric()` to complete the factorization.
7168 
7169   Collective
7170 
7171   Input Parameters:
7172 + fact - the factorized matrix obtained with `MatGetFactor()`
7173 . mat  - the matrix to be factored
7174 . perm - row and column permutation
7175 - info - structure containing
7176 .vb
7177       levels - number of levels of fill.
7178       expected fill - as ratio of original fill.
7179 .ve
7180 
7181   Level: developer
7182 
7183   Notes:
7184   Most users should employ the `KSP` interface for linear solvers
7185   instead of working directly with matrix algebra routines such as this.
7186   See, e.g., `KSPCreate()`.
7187 
7188   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7189 
7190   Developer Note:
7191   The Fortran interface is not autogenerated as the
7192   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7193 
7194 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7195 @*/
7196 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7197 {
7198   PetscFunctionBegin;
7199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7200   PetscValidType(mat, 2);
7201   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7202   PetscAssertPointer(info, 4);
7203   PetscAssertPointer(fact, 1);
7204   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7205   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7206   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7207   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7208   MatCheckPreallocated(mat, 2);
7209 
7210   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7211   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7212   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7213   PetscFunctionReturn(PETSC_SUCCESS);
7214 }
7215 
7216 /*@C
7217   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7218   points to an array of valid matrices, they may be reused to store the new
7219   submatrices.
7220 
7221   Collective
7222 
7223   Input Parameters:
7224 + mat   - the matrix
7225 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7226 . irow  - index set of rows to extract
7227 . icol  - index set of columns to extract
7228 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7229 
7230   Output Parameter:
7231 . submat - the array of submatrices
7232 
7233   Level: advanced
7234 
7235   Notes:
7236   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7237   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7238   to extract a parallel submatrix.
7239 
7240   Some matrix types place restrictions on the row and column
7241   indices, such as that they be sorted or that they be equal to each other.
7242 
7243   The index sets may not have duplicate entries.
7244 
7245   When extracting submatrices from a parallel matrix, each processor can
7246   form a different submatrix by setting the rows and columns of its
7247   individual index sets according to the local submatrix desired.
7248 
7249   When finished using the submatrices, the user should destroy
7250   them with `MatDestroySubMatrices()`.
7251 
7252   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7253   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7254 
7255   This routine creates the matrices in submat; you should NOT create them before
7256   calling it. It also allocates the array of matrix pointers submat.
7257 
7258   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7259   request one row/column in a block, they must request all rows/columns that are in
7260   that block. For example, if the block size is 2 you cannot request just row 0 and
7261   column 0.
7262 
7263   Fortran Note:
7264   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7265 
7266 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7267 @*/
7268 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7269 {
7270   PetscInt  i;
7271   PetscBool eq;
7272 
7273   PetscFunctionBegin;
7274   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7275   PetscValidType(mat, 1);
7276   if (n) {
7277     PetscAssertPointer(irow, 3);
7278     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7279     PetscAssertPointer(icol, 4);
7280     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7281   }
7282   PetscAssertPointer(submat, 6);
7283   if (n && scall == MAT_REUSE_MATRIX) {
7284     PetscAssertPointer(*submat, 6);
7285     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7286   }
7287   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7288   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7289   MatCheckPreallocated(mat, 1);
7290   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7291   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7292   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7293   for (i = 0; i < n; i++) {
7294     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7295     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7296     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7297 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7298     if (mat->boundtocpu && mat->bindingpropagates) {
7299       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7300       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7301     }
7302 #endif
7303   }
7304   PetscFunctionReturn(PETSC_SUCCESS);
7305 }
7306 
7307 /*@C
7308   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7309 
7310   Collective
7311 
7312   Input Parameters:
7313 + mat   - the matrix
7314 . n     - the number of submatrixes to be extracted
7315 . irow  - index set of rows to extract
7316 . icol  - index set of columns to extract
7317 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7318 
7319   Output Parameter:
7320 . submat - the array of submatrices
7321 
7322   Level: advanced
7323 
7324   Note:
7325   This is used by `PCGASM`
7326 
7327 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7328 @*/
7329 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7330 {
7331   PetscInt  i;
7332   PetscBool eq;
7333 
7334   PetscFunctionBegin;
7335   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7336   PetscValidType(mat, 1);
7337   if (n) {
7338     PetscAssertPointer(irow, 3);
7339     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7340     PetscAssertPointer(icol, 4);
7341     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7342   }
7343   PetscAssertPointer(submat, 6);
7344   if (n && scall == MAT_REUSE_MATRIX) {
7345     PetscAssertPointer(*submat, 6);
7346     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7347   }
7348   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7349   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7350   MatCheckPreallocated(mat, 1);
7351 
7352   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7353   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7354   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7355   for (i = 0; i < n; i++) {
7356     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7357     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7358   }
7359   PetscFunctionReturn(PETSC_SUCCESS);
7360 }
7361 
7362 /*@C
7363   MatDestroyMatrices - Destroys an array of matrices.
7364 
7365   Collective
7366 
7367   Input Parameters:
7368 + n   - the number of local matrices
7369 - mat - the matrices (this is a pointer to the array of matrices)
7370 
7371   Level: advanced
7372 
7373   Notes:
7374   Frees not only the matrices, but also the array that contains the matrices
7375 
7376   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7377 
7378   Fortran Note:
7379   Does not free the `mat` array.
7380 
7381 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7382 @*/
7383 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7384 {
7385   PetscInt i;
7386 
7387   PetscFunctionBegin;
7388   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7389   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7390   PetscAssertPointer(mat, 2);
7391 
7392   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7393 
7394   /* memory is allocated even if n = 0 */
7395   PetscCall(PetscFree(*mat));
7396   PetscFunctionReturn(PETSC_SUCCESS);
7397 }
7398 
7399 /*@C
7400   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7401 
7402   Collective
7403 
7404   Input Parameters:
7405 + n   - the number of local matrices
7406 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7407                        sequence of `MatCreateSubMatrices()`)
7408 
7409   Level: advanced
7410 
7411   Note:
7412   Frees not only the matrices, but also the array that contains the matrices
7413 
7414   Fortran Note:
7415   Does not free the `mat` array.
7416 
7417 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7418 @*/
7419 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7420 {
7421   Mat mat0;
7422 
7423   PetscFunctionBegin;
7424   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7425   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7426   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7427   PetscAssertPointer(mat, 2);
7428 
7429   mat0 = (*mat)[0];
7430   if (mat0 && mat0->ops->destroysubmatrices) {
7431     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7432   } else {
7433     PetscCall(MatDestroyMatrices(n, mat));
7434   }
7435   PetscFunctionReturn(PETSC_SUCCESS);
7436 }
7437 
7438 /*@
7439   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7440 
7441   Collective
7442 
7443   Input Parameter:
7444 . mat - the matrix
7445 
7446   Output Parameter:
7447 . matstruct - the sequential matrix with the nonzero structure of `mat`
7448 
7449   Level: developer
7450 
7451 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7452 @*/
7453 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7454 {
7455   PetscFunctionBegin;
7456   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7457   PetscAssertPointer(matstruct, 2);
7458 
7459   PetscValidType(mat, 1);
7460   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7461   MatCheckPreallocated(mat, 1);
7462 
7463   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7464   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7465   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7466   PetscFunctionReturn(PETSC_SUCCESS);
7467 }
7468 
7469 /*@C
7470   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7471 
7472   Collective
7473 
7474   Input Parameter:
7475 . mat - the matrix
7476 
7477   Level: advanced
7478 
7479   Note:
7480   This is not needed, one can just call `MatDestroy()`
7481 
7482 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7483 @*/
7484 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7485 {
7486   PetscFunctionBegin;
7487   PetscAssertPointer(mat, 1);
7488   PetscCall(MatDestroy(mat));
7489   PetscFunctionReturn(PETSC_SUCCESS);
7490 }
7491 
7492 /*@
7493   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7494   replaces the index sets by larger ones that represent submatrices with
7495   additional overlap.
7496 
7497   Collective
7498 
7499   Input Parameters:
7500 + mat - the matrix
7501 . n   - the number of index sets
7502 . is  - the array of index sets (these index sets will changed during the call)
7503 - ov  - the additional overlap requested
7504 
7505   Options Database Key:
7506 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7507 
7508   Level: developer
7509 
7510   Note:
7511   The computed overlap preserves the matrix block sizes when the blocks are square.
7512   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7513   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7514 
7515 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7516 @*/
7517 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7518 {
7519   PetscInt i, bs, cbs;
7520 
7521   PetscFunctionBegin;
7522   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7523   PetscValidType(mat, 1);
7524   PetscValidLogicalCollectiveInt(mat, n, 2);
7525   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7526   if (n) {
7527     PetscAssertPointer(is, 3);
7528     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7529   }
7530   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7531   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7532   MatCheckPreallocated(mat, 1);
7533 
7534   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7535   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7536   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7537   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7538   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7539   if (bs == cbs) {
7540     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7541   }
7542   PetscFunctionReturn(PETSC_SUCCESS);
7543 }
7544 
7545 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7546 
7547 /*@
7548   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7549   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7550   additional overlap.
7551 
7552   Collective
7553 
7554   Input Parameters:
7555 + mat - the matrix
7556 . n   - the number of index sets
7557 . is  - the array of index sets (these index sets will changed during the call)
7558 - ov  - the additional overlap requested
7559 
7560   `   Options Database Key:
7561 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7562 
7563   Level: developer
7564 
7565 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7566 @*/
7567 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7568 {
7569   PetscInt i;
7570 
7571   PetscFunctionBegin;
7572   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7573   PetscValidType(mat, 1);
7574   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7575   if (n) {
7576     PetscAssertPointer(is, 3);
7577     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7578   }
7579   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7580   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7581   MatCheckPreallocated(mat, 1);
7582   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7583   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7584   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7585   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7586   PetscFunctionReturn(PETSC_SUCCESS);
7587 }
7588 
7589 /*@
7590   MatGetBlockSize - Returns the matrix block size.
7591 
7592   Not Collective
7593 
7594   Input Parameter:
7595 . mat - the matrix
7596 
7597   Output Parameter:
7598 . bs - block size
7599 
7600   Level: intermediate
7601 
7602   Notes:
7603   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7604 
7605   If the block size has not been set yet this routine returns 1.
7606 
7607 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7608 @*/
7609 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7610 {
7611   PetscFunctionBegin;
7612   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7613   PetscAssertPointer(bs, 2);
7614   *bs = PetscAbs(mat->rmap->bs);
7615   PetscFunctionReturn(PETSC_SUCCESS);
7616 }
7617 
7618 /*@
7619   MatGetBlockSizes - Returns the matrix block row and column sizes.
7620 
7621   Not Collective
7622 
7623   Input Parameter:
7624 . mat - the matrix
7625 
7626   Output Parameters:
7627 + rbs - row block size
7628 - cbs - column block size
7629 
7630   Level: intermediate
7631 
7632   Notes:
7633   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7634   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7635 
7636   If a block size has not been set yet this routine returns 1.
7637 
7638 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7639 @*/
7640 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7641 {
7642   PetscFunctionBegin;
7643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7644   if (rbs) PetscAssertPointer(rbs, 2);
7645   if (cbs) PetscAssertPointer(cbs, 3);
7646   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7647   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7648   PetscFunctionReturn(PETSC_SUCCESS);
7649 }
7650 
7651 /*@
7652   MatSetBlockSize - Sets the matrix block size.
7653 
7654   Logically Collective
7655 
7656   Input Parameters:
7657 + mat - the matrix
7658 - bs  - block size
7659 
7660   Level: intermediate
7661 
7662   Notes:
7663   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7664   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7665 
7666   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7667   is compatible with the matrix local sizes.
7668 
7669 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7670 @*/
7671 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7672 {
7673   PetscFunctionBegin;
7674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7675   PetscValidLogicalCollectiveInt(mat, bs, 2);
7676   PetscCall(MatSetBlockSizes(mat, bs, bs));
7677   PetscFunctionReturn(PETSC_SUCCESS);
7678 }
7679 
7680 typedef struct {
7681   PetscInt         n;
7682   IS              *is;
7683   Mat             *mat;
7684   PetscObjectState nonzerostate;
7685   Mat              C;
7686 } EnvelopeData;
7687 
7688 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7689 {
7690   EnvelopeData *edata = (EnvelopeData *)*ptr;
7691 
7692   PetscFunctionBegin;
7693   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7694   PetscCall(PetscFree(edata->is));
7695   PetscCall(PetscFree(edata));
7696   PetscFunctionReturn(PETSC_SUCCESS);
7697 }
7698 
7699 /*@
7700   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7701   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7702 
7703   Collective
7704 
7705   Input Parameter:
7706 . mat - the matrix
7707 
7708   Level: intermediate
7709 
7710   Notes:
7711   There can be zeros within the blocks
7712 
7713   The blocks can overlap between processes, including laying on more than two processes
7714 
7715 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7716 @*/
7717 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7718 {
7719   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7720   PetscInt          *diag, *odiag, sc;
7721   VecScatter         scatter;
7722   PetscScalar       *seqv;
7723   const PetscScalar *parv;
7724   const PetscInt    *ia, *ja;
7725   PetscBool          set, flag, done;
7726   Mat                AA = mat, A;
7727   MPI_Comm           comm;
7728   PetscMPIInt        rank, size, tag;
7729   MPI_Status         status;
7730   PetscContainer     container;
7731   EnvelopeData      *edata;
7732   Vec                seq, par;
7733   IS                 isglobal;
7734 
7735   PetscFunctionBegin;
7736   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7737   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7738   if (!set || !flag) {
7739     /* TODO: only needs nonzero structure of transpose */
7740     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7741     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7742   }
7743   PetscCall(MatAIJGetLocalMat(AA, &A));
7744   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7745   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7746 
7747   PetscCall(MatGetLocalSize(mat, &n, NULL));
7748   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7749   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7750   PetscCallMPI(MPI_Comm_size(comm, &size));
7751   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7752 
7753   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7754 
7755   if (rank > 0) {
7756     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7757     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7758   }
7759   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7760   for (i = 0; i < n; i++) {
7761     env = PetscMax(env, ja[ia[i + 1] - 1]);
7762     II  = rstart + i;
7763     if (env == II) {
7764       starts[lblocks]  = tbs;
7765       sizes[lblocks++] = 1 + II - tbs;
7766       tbs              = 1 + II;
7767     }
7768   }
7769   if (rank < size - 1) {
7770     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7771     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7772   }
7773 
7774   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7775   if (!set || !flag) PetscCall(MatDestroy(&AA));
7776   PetscCall(MatDestroy(&A));
7777 
7778   PetscCall(PetscNew(&edata));
7779   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7780   edata->n = lblocks;
7781   /* create IS needed for extracting blocks from the original matrix */
7782   PetscCall(PetscMalloc1(lblocks, &edata->is));
7783   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7784 
7785   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7786   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7787   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7788   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7789   PetscCall(MatSetType(edata->C, MATAIJ));
7790 
7791   /* Communicate the start and end of each row, from each block to the correct rank */
7792   /* TODO: Use PetscSF instead of VecScatter */
7793   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7794   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7795   PetscCall(VecGetArrayWrite(seq, &seqv));
7796   for (PetscInt i = 0; i < lblocks; i++) {
7797     for (PetscInt j = 0; j < sizes[i]; j++) {
7798       seqv[cnt]     = starts[i];
7799       seqv[cnt + 1] = starts[i] + sizes[i];
7800       cnt += 2;
7801     }
7802   }
7803   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7804   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7805   sc -= cnt;
7806   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7807   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7808   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7809   PetscCall(ISDestroy(&isglobal));
7810   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7811   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7812   PetscCall(VecScatterDestroy(&scatter));
7813   PetscCall(VecDestroy(&seq));
7814   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7815   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7816   PetscCall(VecGetArrayRead(par, &parv));
7817   cnt = 0;
7818   PetscCall(MatGetSize(mat, NULL, &n));
7819   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7820     PetscInt start, end, d = 0, od = 0;
7821 
7822     start = (PetscInt)PetscRealPart(parv[cnt]);
7823     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7824     cnt += 2;
7825 
7826     if (start < cstart) {
7827       od += cstart - start + n - cend;
7828       d += cend - cstart;
7829     } else if (start < cend) {
7830       od += n - cend;
7831       d += cend - start;
7832     } else od += n - start;
7833     if (end <= cstart) {
7834       od -= cstart - end + n - cend;
7835       d -= cend - cstart;
7836     } else if (end < cend) {
7837       od -= n - cend;
7838       d -= cend - end;
7839     } else od -= n - end;
7840 
7841     odiag[i] = od;
7842     diag[i]  = d;
7843   }
7844   PetscCall(VecRestoreArrayRead(par, &parv));
7845   PetscCall(VecDestroy(&par));
7846   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7847   PetscCall(PetscFree2(diag, odiag));
7848   PetscCall(PetscFree2(sizes, starts));
7849 
7850   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7851   PetscCall(PetscContainerSetPointer(container, edata));
7852   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7853   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7854   PetscCall(PetscObjectDereference((PetscObject)container));
7855   PetscFunctionReturn(PETSC_SUCCESS);
7856 }
7857 
7858 /*@
7859   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7860 
7861   Collective
7862 
7863   Input Parameters:
7864 + A     - the matrix
7865 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7866 
7867   Output Parameter:
7868 . C - matrix with inverted block diagonal of `A`
7869 
7870   Level: advanced
7871 
7872   Note:
7873   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7874 
7875 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7876 @*/
7877 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7878 {
7879   PetscContainer   container;
7880   EnvelopeData    *edata;
7881   PetscObjectState nonzerostate;
7882 
7883   PetscFunctionBegin;
7884   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7885   if (!container) {
7886     PetscCall(MatComputeVariableBlockEnvelope(A));
7887     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7888   }
7889   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7890   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7891   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7892   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7893 
7894   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7895   *C = edata->C;
7896 
7897   for (PetscInt i = 0; i < edata->n; i++) {
7898     Mat          D;
7899     PetscScalar *dvalues;
7900 
7901     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7902     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7903     PetscCall(MatSeqDenseInvert(D));
7904     PetscCall(MatDenseGetArray(D, &dvalues));
7905     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7906     PetscCall(MatDestroy(&D));
7907   }
7908   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7909   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7910   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7911   PetscFunctionReturn(PETSC_SUCCESS);
7912 }
7913 
7914 /*@
7915   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7916 
7917   Not Collective
7918 
7919   Input Parameters:
7920 + mat     - the matrix
7921 . nblocks - the number of blocks on this process, each block can only exist on a single process
7922 - bsizes  - the block sizes
7923 
7924   Level: intermediate
7925 
7926   Notes:
7927   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7928 
7929   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.
7930 
7931 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7932           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7933 @*/
7934 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7935 {
7936   PetscInt ncnt = 0, nlocal;
7937 
7938   PetscFunctionBegin;
7939   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7940   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7941   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);
7942   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7943   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);
7944   PetscCall(PetscFree(mat->bsizes));
7945   mat->nblocks = nblocks;
7946   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7947   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7948   PetscFunctionReturn(PETSC_SUCCESS);
7949 }
7950 
7951 /*@C
7952   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7953 
7954   Not Collective; No Fortran Support
7955 
7956   Input Parameter:
7957 . mat - the matrix
7958 
7959   Output Parameters:
7960 + nblocks - the number of blocks on this process
7961 - bsizes  - the block sizes
7962 
7963   Level: intermediate
7964 
7965 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7966 @*/
7967 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7968 {
7969   PetscFunctionBegin;
7970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7971   if (nblocks) *nblocks = mat->nblocks;
7972   if (bsizes) *bsizes = mat->bsizes;
7973   PetscFunctionReturn(PETSC_SUCCESS);
7974 }
7975 
7976 /*@
7977   MatSetBlockSizes - Sets the matrix block row and column sizes.
7978 
7979   Logically Collective
7980 
7981   Input Parameters:
7982 + mat - the matrix
7983 . rbs - row block size
7984 - cbs - column block size
7985 
7986   Level: intermediate
7987 
7988   Notes:
7989   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7990   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7991   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7992 
7993   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7994   are compatible with the matrix local sizes.
7995 
7996   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7997 
7998 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7999 @*/
8000 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
8001 {
8002   PetscFunctionBegin;
8003   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8004   PetscValidLogicalCollectiveInt(mat, rbs, 2);
8005   PetscValidLogicalCollectiveInt(mat, cbs, 3);
8006   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
8007   if (mat->rmap->refcnt) {
8008     ISLocalToGlobalMapping l2g  = NULL;
8009     PetscLayout            nmap = NULL;
8010 
8011     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
8012     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
8013     PetscCall(PetscLayoutDestroy(&mat->rmap));
8014     mat->rmap          = nmap;
8015     mat->rmap->mapping = l2g;
8016   }
8017   if (mat->cmap->refcnt) {
8018     ISLocalToGlobalMapping l2g  = NULL;
8019     PetscLayout            nmap = NULL;
8020 
8021     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
8022     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
8023     PetscCall(PetscLayoutDestroy(&mat->cmap));
8024     mat->cmap          = nmap;
8025     mat->cmap->mapping = l2g;
8026   }
8027   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
8028   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
8029   PetscFunctionReturn(PETSC_SUCCESS);
8030 }
8031 
8032 /*@
8033   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
8034 
8035   Logically Collective
8036 
8037   Input Parameters:
8038 + mat     - the matrix
8039 . fromRow - matrix from which to copy row block size
8040 - fromCol - matrix from which to copy column block size (can be same as fromRow)
8041 
8042   Level: developer
8043 
8044 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
8045 @*/
8046 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8047 {
8048   PetscFunctionBegin;
8049   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8050   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8051   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8052   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8053   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8054   PetscFunctionReturn(PETSC_SUCCESS);
8055 }
8056 
8057 /*@
8058   MatResidual - Default routine to calculate the residual r = b - Ax
8059 
8060   Collective
8061 
8062   Input Parameters:
8063 + mat - the matrix
8064 . b   - the right-hand-side
8065 - x   - the approximate solution
8066 
8067   Output Parameter:
8068 . r - location to store the residual
8069 
8070   Level: developer
8071 
8072 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8073 @*/
8074 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8075 {
8076   PetscFunctionBegin;
8077   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8078   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8079   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8080   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8081   PetscValidType(mat, 1);
8082   MatCheckPreallocated(mat, 1);
8083   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8084   if (!mat->ops->residual) {
8085     PetscCall(MatMult(mat, x, r));
8086     PetscCall(VecAYPX(r, -1.0, b));
8087   } else {
8088     PetscUseTypeMethod(mat, residual, b, x, r);
8089   }
8090   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8091   PetscFunctionReturn(PETSC_SUCCESS);
8092 }
8093 
8094 /*MC
8095     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8096 
8097     Synopsis:
8098     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8099 
8100     Not Collective
8101 
8102     Input Parameters:
8103 +   A - the matrix
8104 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8105 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8106 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8107                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8108                  always used.
8109 
8110     Output Parameters:
8111 +   n - number of local rows in the (possibly compressed) matrix
8112 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8113 .   ja - the column indices
8114 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8115            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8116 
8117     Level: developer
8118 
8119     Note:
8120     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8121 
8122 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8123 M*/
8124 
8125 /*MC
8126     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8127 
8128     Synopsis:
8129     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8130 
8131     Not Collective
8132 
8133     Input Parameters:
8134 +   A - the  matrix
8135 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8136 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8137     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8138                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8139                  always used.
8140 .   n - number of local rows in the (possibly compressed) matrix
8141 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8142 .   ja - the column indices
8143 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8144            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8145 
8146     Level: developer
8147 
8148 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8149 M*/
8150 
8151 /*@C
8152   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8153 
8154   Collective
8155 
8156   Input Parameters:
8157 + mat             - the matrix
8158 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8159 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8160 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8161                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8162                  always used.
8163 
8164   Output Parameters:
8165 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8166 . 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
8167 . ja   - the column indices, use `NULL` if not needed
8168 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8169            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8170 
8171   Level: developer
8172 
8173   Notes:
8174   You CANNOT change any of the ia[] or ja[] values.
8175 
8176   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8177 
8178   Fortran Notes:
8179   Use
8180 .vb
8181     PetscInt, pointer :: ia(:),ja(:)
8182     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8183     ! Access the ith and jth entries via ia(i) and ja(j)
8184 .ve
8185 
8186   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8187 
8188 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8189 @*/
8190 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8191 {
8192   PetscFunctionBegin;
8193   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8194   PetscValidType(mat, 1);
8195   if (n) PetscAssertPointer(n, 5);
8196   if (ia) PetscAssertPointer(ia, 6);
8197   if (ja) PetscAssertPointer(ja, 7);
8198   if (done) PetscAssertPointer(done, 8);
8199   MatCheckPreallocated(mat, 1);
8200   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8201   else {
8202     if (done) *done = PETSC_TRUE;
8203     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8204     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8205     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8206   }
8207   PetscFunctionReturn(PETSC_SUCCESS);
8208 }
8209 
8210 /*@C
8211   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8212 
8213   Collective
8214 
8215   Input Parameters:
8216 + mat             - the matrix
8217 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8218 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8219                 symmetrized
8220 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8221                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8222                  always used.
8223 . n               - number of columns in the (possibly compressed) matrix
8224 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8225 - ja              - the row indices
8226 
8227   Output Parameter:
8228 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8229 
8230   Level: developer
8231 
8232 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8233 @*/
8234 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8235 {
8236   PetscFunctionBegin;
8237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8238   PetscValidType(mat, 1);
8239   PetscAssertPointer(n, 5);
8240   if (ia) PetscAssertPointer(ia, 6);
8241   if (ja) PetscAssertPointer(ja, 7);
8242   PetscAssertPointer(done, 8);
8243   MatCheckPreallocated(mat, 1);
8244   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8245   else {
8246     *done = PETSC_TRUE;
8247     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8248   }
8249   PetscFunctionReturn(PETSC_SUCCESS);
8250 }
8251 
8252 /*@C
8253   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8254 
8255   Collective
8256 
8257   Input Parameters:
8258 + mat             - the matrix
8259 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8260 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8261 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8262                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8263                     always used.
8264 . n               - size of (possibly compressed) matrix
8265 . ia              - the row pointers
8266 - ja              - the column indices
8267 
8268   Output Parameter:
8269 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8270 
8271   Level: developer
8272 
8273   Note:
8274   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8275   us of the array after it has been restored. If you pass `NULL`, it will
8276   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8277 
8278   Fortran Note:
8279   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8280 
8281 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8282 @*/
8283 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8284 {
8285   PetscFunctionBegin;
8286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8287   PetscValidType(mat, 1);
8288   if (ia) PetscAssertPointer(ia, 6);
8289   if (ja) PetscAssertPointer(ja, 7);
8290   if (done) PetscAssertPointer(done, 8);
8291   MatCheckPreallocated(mat, 1);
8292 
8293   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8294   else {
8295     if (done) *done = PETSC_TRUE;
8296     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8297     if (n) *n = 0;
8298     if (ia) *ia = NULL;
8299     if (ja) *ja = NULL;
8300   }
8301   PetscFunctionReturn(PETSC_SUCCESS);
8302 }
8303 
8304 /*@C
8305   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8306 
8307   Collective
8308 
8309   Input Parameters:
8310 + mat             - the matrix
8311 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8312 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8313 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8314                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8315                     always used.
8316 
8317   Output Parameters:
8318 + n    - size of (possibly compressed) matrix
8319 . ia   - the column pointers
8320 . ja   - the row indices
8321 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8322 
8323   Level: developer
8324 
8325 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8326 @*/
8327 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8328 {
8329   PetscFunctionBegin;
8330   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8331   PetscValidType(mat, 1);
8332   if (ia) PetscAssertPointer(ia, 6);
8333   if (ja) PetscAssertPointer(ja, 7);
8334   PetscAssertPointer(done, 8);
8335   MatCheckPreallocated(mat, 1);
8336 
8337   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8338   else {
8339     *done = PETSC_TRUE;
8340     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8341     if (n) *n = 0;
8342     if (ia) *ia = NULL;
8343     if (ja) *ja = NULL;
8344   }
8345   PetscFunctionReturn(PETSC_SUCCESS);
8346 }
8347 
8348 /*@
8349   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8350   `MatGetColumnIJ()`.
8351 
8352   Collective
8353 
8354   Input Parameters:
8355 + mat        - the matrix
8356 . ncolors    - maximum color value
8357 . n          - number of entries in colorarray
8358 - colorarray - array indicating color for each column
8359 
8360   Output Parameter:
8361 . iscoloring - coloring generated using colorarray information
8362 
8363   Level: developer
8364 
8365 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8366 @*/
8367 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8368 {
8369   PetscFunctionBegin;
8370   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8371   PetscValidType(mat, 1);
8372   PetscAssertPointer(colorarray, 4);
8373   PetscAssertPointer(iscoloring, 5);
8374   MatCheckPreallocated(mat, 1);
8375 
8376   if (!mat->ops->coloringpatch) {
8377     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8378   } else {
8379     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8380   }
8381   PetscFunctionReturn(PETSC_SUCCESS);
8382 }
8383 
8384 /*@
8385   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8386 
8387   Logically Collective
8388 
8389   Input Parameter:
8390 . mat - the factored matrix to be reset
8391 
8392   Level: developer
8393 
8394   Notes:
8395   This routine should be used only with factored matrices formed by in-place
8396   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8397   format).  This option can save memory, for example, when solving nonlinear
8398   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8399   ILU(0) preconditioner.
8400 
8401   One can specify in-place ILU(0) factorization by calling
8402 .vb
8403      PCType(pc,PCILU);
8404      PCFactorSeUseInPlace(pc);
8405 .ve
8406   or by using the options -pc_type ilu -pc_factor_in_place
8407 
8408   In-place factorization ILU(0) can also be used as a local
8409   solver for the blocks within the block Jacobi or additive Schwarz
8410   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8411   for details on setting local solver options.
8412 
8413   Most users should employ the `KSP` interface for linear solvers
8414   instead of working directly with matrix algebra routines such as this.
8415   See, e.g., `KSPCreate()`.
8416 
8417 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8418 @*/
8419 PetscErrorCode MatSetUnfactored(Mat mat)
8420 {
8421   PetscFunctionBegin;
8422   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8423   PetscValidType(mat, 1);
8424   MatCheckPreallocated(mat, 1);
8425   mat->factortype = MAT_FACTOR_NONE;
8426   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8427   PetscUseTypeMethod(mat, setunfactored);
8428   PetscFunctionReturn(PETSC_SUCCESS);
8429 }
8430 
8431 /*MC
8432     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8433 
8434     Synopsis:
8435     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8436 
8437     Not Collective
8438 
8439     Input Parameter:
8440 .   x - matrix
8441 
8442     Output Parameters:
8443 +   xx_v - the Fortran pointer to the array
8444 -   ierr - error code
8445 
8446     Example of Usage:
8447 .vb
8448       PetscScalar, pointer xx_v(:,:)
8449       ....
8450       call MatDenseGetArrayF90(x,xx_v,ierr)
8451       a = xx_v(3)
8452       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8453 .ve
8454 
8455     Level: advanced
8456 
8457 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8458 M*/
8459 
8460 /*MC
8461     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8462     accessed with `MatDenseGetArrayF90()`.
8463 
8464     Synopsis:
8465     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8466 
8467     Not Collective
8468 
8469     Input Parameters:
8470 +   x - matrix
8471 -   xx_v - the Fortran90 pointer to the array
8472 
8473     Output Parameter:
8474 .   ierr - error code
8475 
8476     Example of Usage:
8477 .vb
8478        PetscScalar, pointer xx_v(:,:)
8479        ....
8480        call MatDenseGetArrayF90(x,xx_v,ierr)
8481        a = xx_v(3)
8482        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8483 .ve
8484 
8485     Level: advanced
8486 
8487 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8488 M*/
8489 
8490 /*MC
8491     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8492 
8493     Synopsis:
8494     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8495 
8496     Not Collective
8497 
8498     Input Parameter:
8499 .   x - matrix
8500 
8501     Output Parameters:
8502 +   xx_v - the Fortran pointer to the array
8503 -   ierr - error code
8504 
8505     Example of Usage:
8506 .vb
8507       PetscScalar, pointer xx_v(:)
8508       ....
8509       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8510       a = xx_v(3)
8511       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8512 .ve
8513 
8514     Level: advanced
8515 
8516 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8517 M*/
8518 
8519 /*MC
8520     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8521     accessed with `MatSeqAIJGetArrayF90()`.
8522 
8523     Synopsis:
8524     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8525 
8526     Not Collective
8527 
8528     Input Parameters:
8529 +   x - matrix
8530 -   xx_v - the Fortran90 pointer to the array
8531 
8532     Output Parameter:
8533 .   ierr - error code
8534 
8535     Example of Usage:
8536 .vb
8537        PetscScalar, pointer xx_v(:)
8538        ....
8539        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8540        a = xx_v(3)
8541        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8542 .ve
8543 
8544     Level: advanced
8545 
8546 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8547 M*/
8548 
8549 /*@
8550   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8551   as the original matrix.
8552 
8553   Collective
8554 
8555   Input Parameters:
8556 + mat   - the original matrix
8557 . isrow - parallel `IS` containing the rows this processor should obtain
8558 . 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.
8559 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8560 
8561   Output Parameter:
8562 . newmat - the new submatrix, of the same type as the original matrix
8563 
8564   Level: advanced
8565 
8566   Notes:
8567   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8568 
8569   Some matrix types place restrictions on the row and column indices, such
8570   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;
8571   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8572 
8573   The index sets may not have duplicate entries.
8574 
8575   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8576   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8577   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8578   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8579   you are finished using it.
8580 
8581   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8582   the input matrix.
8583 
8584   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8585 
8586   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8587   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8588 
8589   Example usage:
8590   Consider the following 8x8 matrix with 34 non-zero values, that is
8591   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8592   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8593   as follows
8594 .vb
8595             1  2  0  |  0  3  0  |  0  4
8596     Proc0   0  5  6  |  7  0  0  |  8  0
8597             9  0 10  | 11  0  0  | 12  0
8598     -------------------------------------
8599            13  0 14  | 15 16 17  |  0  0
8600     Proc1   0 18  0  | 19 20 21  |  0  0
8601             0  0  0  | 22 23  0  | 24  0
8602     -------------------------------------
8603     Proc2  25 26 27  |  0  0 28  | 29  0
8604            30  0  0  | 31 32 33  |  0 34
8605 .ve
8606 
8607   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8608 
8609 .vb
8610             2  0  |  0  3  0  |  0
8611     Proc0   5  6  |  7  0  0  |  8
8612     -------------------------------
8613     Proc1  18  0  | 19 20 21  |  0
8614     -------------------------------
8615     Proc2  26 27  |  0  0 28  | 29
8616             0  0  | 31 32 33  |  0
8617 .ve
8618 
8619 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8620 @*/
8621 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8622 {
8623   PetscMPIInt size;
8624   Mat        *local;
8625   IS          iscoltmp;
8626   PetscBool   flg;
8627 
8628   PetscFunctionBegin;
8629   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8630   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8631   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8632   PetscAssertPointer(newmat, 5);
8633   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8634   PetscValidType(mat, 1);
8635   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8636   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8637 
8638   MatCheckPreallocated(mat, 1);
8639   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8640 
8641   if (!iscol || isrow == iscol) {
8642     PetscBool   stride;
8643     PetscMPIInt grabentirematrix = 0, grab;
8644     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8645     if (stride) {
8646       PetscInt first, step, n, rstart, rend;
8647       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8648       if (step == 1) {
8649         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8650         if (rstart == first) {
8651           PetscCall(ISGetLocalSize(isrow, &n));
8652           if (n == rend - rstart) grabentirematrix = 1;
8653         }
8654       }
8655     }
8656     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8657     if (grab) {
8658       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8659       if (cll == MAT_INITIAL_MATRIX) {
8660         *newmat = mat;
8661         PetscCall(PetscObjectReference((PetscObject)mat));
8662       }
8663       PetscFunctionReturn(PETSC_SUCCESS);
8664     }
8665   }
8666 
8667   if (!iscol) {
8668     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8669   } else {
8670     iscoltmp = iscol;
8671   }
8672 
8673   /* if original matrix is on just one processor then use submatrix generated */
8674   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8675     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8676     goto setproperties;
8677   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8678     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8679     *newmat = *local;
8680     PetscCall(PetscFree(local));
8681     goto setproperties;
8682   } else if (!mat->ops->createsubmatrix) {
8683     /* Create a new matrix type that implements the operation using the full matrix */
8684     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8685     switch (cll) {
8686     case MAT_INITIAL_MATRIX:
8687       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8688       break;
8689     case MAT_REUSE_MATRIX:
8690       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8691       break;
8692     default:
8693       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8694     }
8695     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8696     goto setproperties;
8697   }
8698 
8699   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8700   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8701   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8702 
8703 setproperties:
8704   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8705     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8706     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8707   }
8708   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8709   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8710   PetscFunctionReturn(PETSC_SUCCESS);
8711 }
8712 
8713 /*@
8714   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8715 
8716   Not Collective
8717 
8718   Input Parameters:
8719 + A - the matrix we wish to propagate options from
8720 - B - the matrix we wish to propagate options to
8721 
8722   Level: beginner
8723 
8724   Note:
8725   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8726 
8727 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8728 @*/
8729 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8730 {
8731   PetscFunctionBegin;
8732   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8733   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8734   B->symmetry_eternal            = A->symmetry_eternal;
8735   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8736   B->symmetric                   = A->symmetric;
8737   B->structurally_symmetric      = A->structurally_symmetric;
8738   B->spd                         = A->spd;
8739   B->hermitian                   = A->hermitian;
8740   PetscFunctionReturn(PETSC_SUCCESS);
8741 }
8742 
8743 /*@
8744   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8745   used during the assembly process to store values that belong to
8746   other processors.
8747 
8748   Not Collective
8749 
8750   Input Parameters:
8751 + mat   - the matrix
8752 . size  - the initial size of the stash.
8753 - bsize - the initial size of the block-stash(if used).
8754 
8755   Options Database Keys:
8756 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8757 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8758 
8759   Level: intermediate
8760 
8761   Notes:
8762   The block-stash is used for values set with `MatSetValuesBlocked()` while
8763   the stash is used for values set with `MatSetValues()`
8764 
8765   Run with the option -info and look for output of the form
8766   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8767   to determine the appropriate value, MM, to use for size and
8768   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8769   to determine the value, BMM to use for bsize
8770 
8771 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8772 @*/
8773 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8774 {
8775   PetscFunctionBegin;
8776   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8777   PetscValidType(mat, 1);
8778   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8779   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8780   PetscFunctionReturn(PETSC_SUCCESS);
8781 }
8782 
8783 /*@
8784   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8785   the matrix
8786 
8787   Neighbor-wise Collective
8788 
8789   Input Parameters:
8790 + A - the matrix
8791 . x - the vector to be multiplied by the interpolation operator
8792 - y - the vector to be added to the result
8793 
8794   Output Parameter:
8795 . w - the resulting vector
8796 
8797   Level: intermediate
8798 
8799   Notes:
8800   `w` may be the same vector as `y`.
8801 
8802   This allows one to use either the restriction or interpolation (its transpose)
8803   matrix to do the interpolation
8804 
8805 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8806 @*/
8807 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8808 {
8809   PetscInt M, N, Ny;
8810 
8811   PetscFunctionBegin;
8812   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8813   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8814   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8815   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8816   PetscCall(MatGetSize(A, &M, &N));
8817   PetscCall(VecGetSize(y, &Ny));
8818   if (M == Ny) {
8819     PetscCall(MatMultAdd(A, x, y, w));
8820   } else {
8821     PetscCall(MatMultTransposeAdd(A, x, y, w));
8822   }
8823   PetscFunctionReturn(PETSC_SUCCESS);
8824 }
8825 
8826 /*@
8827   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8828   the matrix
8829 
8830   Neighbor-wise Collective
8831 
8832   Input Parameters:
8833 + A - the matrix
8834 - x - the vector to be interpolated
8835 
8836   Output Parameter:
8837 . y - the resulting vector
8838 
8839   Level: intermediate
8840 
8841   Note:
8842   This allows one to use either the restriction or interpolation (its transpose)
8843   matrix to do the interpolation
8844 
8845 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8846 @*/
8847 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8848 {
8849   PetscInt M, N, Ny;
8850 
8851   PetscFunctionBegin;
8852   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8853   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8854   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8855   PetscCall(MatGetSize(A, &M, &N));
8856   PetscCall(VecGetSize(y, &Ny));
8857   if (M == Ny) {
8858     PetscCall(MatMult(A, x, y));
8859   } else {
8860     PetscCall(MatMultTranspose(A, x, y));
8861   }
8862   PetscFunctionReturn(PETSC_SUCCESS);
8863 }
8864 
8865 /*@
8866   MatRestrict - $y = A*x$ or $A^T*x$
8867 
8868   Neighbor-wise Collective
8869 
8870   Input Parameters:
8871 + A - the matrix
8872 - x - the vector to be restricted
8873 
8874   Output Parameter:
8875 . y - the resulting vector
8876 
8877   Level: intermediate
8878 
8879   Note:
8880   This allows one to use either the restriction or interpolation (its transpose)
8881   matrix to do the restriction
8882 
8883 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8884 @*/
8885 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8886 {
8887   PetscInt M, N, Nx;
8888 
8889   PetscFunctionBegin;
8890   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8891   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8892   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8893   PetscCall(MatGetSize(A, &M, &N));
8894   PetscCall(VecGetSize(x, &Nx));
8895   if (M == Nx) {
8896     PetscCall(MatMultTranspose(A, x, y));
8897   } else {
8898     PetscCall(MatMult(A, x, y));
8899   }
8900   PetscFunctionReturn(PETSC_SUCCESS);
8901 }
8902 
8903 /*@
8904   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8905 
8906   Neighbor-wise Collective
8907 
8908   Input Parameters:
8909 + A - the matrix
8910 . x - the input dense matrix to be multiplied
8911 - w - the input dense matrix to be added to the result
8912 
8913   Output Parameter:
8914 . y - the output dense matrix
8915 
8916   Level: intermediate
8917 
8918   Note:
8919   This allows one to use either the restriction or interpolation (its transpose)
8920   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8921   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8922 
8923 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8924 @*/
8925 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8926 {
8927   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8928   PetscBool trans = PETSC_TRUE;
8929   MatReuse  reuse = MAT_INITIAL_MATRIX;
8930 
8931   PetscFunctionBegin;
8932   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8933   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8934   PetscValidType(x, 2);
8935   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8936   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8937   PetscCall(MatGetSize(A, &M, &N));
8938   PetscCall(MatGetSize(x, &Mx, &Nx));
8939   if (N == Mx) trans = PETSC_FALSE;
8940   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);
8941   Mo = trans ? N : M;
8942   if (*y) {
8943     PetscCall(MatGetSize(*y, &My, &Ny));
8944     if (Mo == My && Nx == Ny) {
8945       reuse = MAT_REUSE_MATRIX;
8946     } else {
8947       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);
8948       PetscCall(MatDestroy(y));
8949     }
8950   }
8951 
8952   if (w && *y == w) { /* this is to minimize changes in PCMG */
8953     PetscBool flg;
8954 
8955     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8956     if (w) {
8957       PetscInt My, Ny, Mw, Nw;
8958 
8959       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8960       PetscCall(MatGetSize(*y, &My, &Ny));
8961       PetscCall(MatGetSize(w, &Mw, &Nw));
8962       if (!flg || My != Mw || Ny != Nw) w = NULL;
8963     }
8964     if (!w) {
8965       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8966       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8967       PetscCall(PetscObjectDereference((PetscObject)w));
8968     } else {
8969       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8970     }
8971   }
8972   if (!trans) {
8973     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8974   } else {
8975     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8976   }
8977   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8978   PetscFunctionReturn(PETSC_SUCCESS);
8979 }
8980 
8981 /*@
8982   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8983 
8984   Neighbor-wise Collective
8985 
8986   Input Parameters:
8987 + A - the matrix
8988 - x - the input dense matrix
8989 
8990   Output Parameter:
8991 . y - the output dense matrix
8992 
8993   Level: intermediate
8994 
8995   Note:
8996   This allows one to use either the restriction or interpolation (its transpose)
8997   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8998   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8999 
9000 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
9001 @*/
9002 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
9003 {
9004   PetscFunctionBegin;
9005   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
9006   PetscFunctionReturn(PETSC_SUCCESS);
9007 }
9008 
9009 /*@
9010   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
9011 
9012   Neighbor-wise Collective
9013 
9014   Input Parameters:
9015 + A - the matrix
9016 - x - the input dense matrix
9017 
9018   Output Parameter:
9019 . y - the output dense matrix
9020 
9021   Level: intermediate
9022 
9023   Note:
9024   This allows one to use either the restriction or interpolation (its transpose)
9025   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
9026   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
9027 
9028 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
9029 @*/
9030 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
9031 {
9032   PetscFunctionBegin;
9033   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
9034   PetscFunctionReturn(PETSC_SUCCESS);
9035 }
9036 
9037 /*@
9038   MatGetNullSpace - retrieves the null space of a matrix.
9039 
9040   Logically Collective
9041 
9042   Input Parameters:
9043 + mat    - the matrix
9044 - nullsp - the null space object
9045 
9046   Level: developer
9047 
9048 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
9049 @*/
9050 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
9051 {
9052   PetscFunctionBegin;
9053   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9054   PetscAssertPointer(nullsp, 2);
9055   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
9056   PetscFunctionReturn(PETSC_SUCCESS);
9057 }
9058 
9059 /*@C
9060   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
9061 
9062   Logically Collective
9063 
9064   Input Parameters:
9065 + n   - the number of matrices
9066 - mat - the array of matrices
9067 
9068   Output Parameters:
9069 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
9070 
9071   Level: developer
9072 
9073   Note:
9074   Call `MatRestoreNullspaces()` to provide these to another array of matrices
9075 
9076 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9077           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
9078 @*/
9079 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9080 {
9081   PetscFunctionBegin;
9082   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9083   PetscAssertPointer(mat, 2);
9084   PetscAssertPointer(nullsp, 3);
9085 
9086   PetscCall(PetscCalloc1(3 * n, nullsp));
9087   for (PetscInt i = 0; i < n; i++) {
9088     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9089     (*nullsp)[i] = mat[i]->nullsp;
9090     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9091     (*nullsp)[n + i] = mat[i]->nearnullsp;
9092     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9093     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9094     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9095   }
9096   PetscFunctionReturn(PETSC_SUCCESS);
9097 }
9098 
9099 /*@C
9100   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9101 
9102   Logically Collective
9103 
9104   Input Parameters:
9105 + n      - the number of matrices
9106 . mat    - the array of matrices
9107 - nullsp - an array of null spaces
9108 
9109   Level: developer
9110 
9111   Note:
9112   Call `MatGetNullSpaces()` to create `nullsp`
9113 
9114 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9115           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9116 @*/
9117 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9118 {
9119   PetscFunctionBegin;
9120   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9121   PetscAssertPointer(mat, 2);
9122   PetscAssertPointer(nullsp, 3);
9123   PetscAssertPointer(*nullsp, 3);
9124 
9125   for (PetscInt i = 0; i < n; i++) {
9126     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9127     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9128     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9129     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9130     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9131     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9132     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9133   }
9134   PetscCall(PetscFree(*nullsp));
9135   PetscFunctionReturn(PETSC_SUCCESS);
9136 }
9137 
9138 /*@
9139   MatSetNullSpace - attaches a null space to a matrix.
9140 
9141   Logically Collective
9142 
9143   Input Parameters:
9144 + mat    - the matrix
9145 - nullsp - the null space object
9146 
9147   Level: advanced
9148 
9149   Notes:
9150   This null space is used by the `KSP` linear solvers to solve singular systems.
9151 
9152   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`
9153 
9154   For inconsistent singular systems (linear systems where the right-hand side is not in the range of the operator) the `KSP` residuals will not converge to
9155   to zero but the linear system will still be solved in a least squares sense.
9156 
9157   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9158   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)$.
9159   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
9160   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
9161   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$).
9162   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9163 
9164   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9165   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9166   routine also automatically calls `MatSetTransposeNullSpace()`.
9167 
9168   The user should call `MatNullSpaceDestroy()`.
9169 
9170 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9171           `KSPSetPCSide()`
9172 @*/
9173 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9174 {
9175   PetscFunctionBegin;
9176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9177   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9178   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9179   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9180   mat->nullsp = nullsp;
9181   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9182   PetscFunctionReturn(PETSC_SUCCESS);
9183 }
9184 
9185 /*@
9186   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9187 
9188   Logically Collective
9189 
9190   Input Parameters:
9191 + mat    - the matrix
9192 - nullsp - the null space object
9193 
9194   Level: developer
9195 
9196 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9197 @*/
9198 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9199 {
9200   PetscFunctionBegin;
9201   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9202   PetscValidType(mat, 1);
9203   PetscAssertPointer(nullsp, 2);
9204   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9205   PetscFunctionReturn(PETSC_SUCCESS);
9206 }
9207 
9208 /*@
9209   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9210 
9211   Logically Collective
9212 
9213   Input Parameters:
9214 + mat    - the matrix
9215 - nullsp - the null space object
9216 
9217   Level: advanced
9218 
9219   Notes:
9220   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9221 
9222   See `MatSetNullSpace()`
9223 
9224 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9225 @*/
9226 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9227 {
9228   PetscFunctionBegin;
9229   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9230   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9231   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9232   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9233   mat->transnullsp = nullsp;
9234   PetscFunctionReturn(PETSC_SUCCESS);
9235 }
9236 
9237 /*@
9238   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9239   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9240 
9241   Logically Collective
9242 
9243   Input Parameters:
9244 + mat    - the matrix
9245 - nullsp - the null space object
9246 
9247   Level: advanced
9248 
9249   Notes:
9250   Overwrites any previous near null space that may have been attached
9251 
9252   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9253 
9254 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9255 @*/
9256 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9257 {
9258   PetscFunctionBegin;
9259   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9260   PetscValidType(mat, 1);
9261   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9262   MatCheckPreallocated(mat, 1);
9263   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9264   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9265   mat->nearnullsp = nullsp;
9266   PetscFunctionReturn(PETSC_SUCCESS);
9267 }
9268 
9269 /*@
9270   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9271 
9272   Not Collective
9273 
9274   Input Parameter:
9275 . mat - the matrix
9276 
9277   Output Parameter:
9278 . nullsp - the null space object, `NULL` if not set
9279 
9280   Level: advanced
9281 
9282 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9283 @*/
9284 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9285 {
9286   PetscFunctionBegin;
9287   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9288   PetscValidType(mat, 1);
9289   PetscAssertPointer(nullsp, 2);
9290   MatCheckPreallocated(mat, 1);
9291   *nullsp = mat->nearnullsp;
9292   PetscFunctionReturn(PETSC_SUCCESS);
9293 }
9294 
9295 /*@
9296   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9297 
9298   Collective
9299 
9300   Input Parameters:
9301 + mat  - the matrix
9302 . row  - row/column permutation
9303 - info - information on desired factorization process
9304 
9305   Level: developer
9306 
9307   Notes:
9308   Probably really in-place only when level of fill is zero, otherwise allocates
9309   new space to store factored matrix and deletes previous memory.
9310 
9311   Most users should employ the `KSP` interface for linear solvers
9312   instead of working directly with matrix algebra routines such as this.
9313   See, e.g., `KSPCreate()`.
9314 
9315   Developer Note:
9316   The Fortran interface is not autogenerated as the
9317   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9318 
9319 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9320 @*/
9321 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9322 {
9323   PetscFunctionBegin;
9324   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9325   PetscValidType(mat, 1);
9326   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9327   PetscAssertPointer(info, 3);
9328   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9329   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9330   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9331   MatCheckPreallocated(mat, 1);
9332   PetscUseTypeMethod(mat, iccfactor, row, info);
9333   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9334   PetscFunctionReturn(PETSC_SUCCESS);
9335 }
9336 
9337 /*@
9338   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9339   ghosted ones.
9340 
9341   Not Collective
9342 
9343   Input Parameters:
9344 + mat  - the matrix
9345 - diag - the diagonal values, including ghost ones
9346 
9347   Level: developer
9348 
9349   Notes:
9350   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9351 
9352   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9353 
9354 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9355 @*/
9356 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9357 {
9358   PetscMPIInt size;
9359 
9360   PetscFunctionBegin;
9361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9362   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9363   PetscValidType(mat, 1);
9364 
9365   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9366   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9367   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9368   if (size == 1) {
9369     PetscInt n, m;
9370     PetscCall(VecGetSize(diag, &n));
9371     PetscCall(MatGetSize(mat, NULL, &m));
9372     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9373     PetscCall(MatDiagonalScale(mat, NULL, diag));
9374   } else {
9375     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9376   }
9377   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9378   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9379   PetscFunctionReturn(PETSC_SUCCESS);
9380 }
9381 
9382 /*@
9383   MatGetInertia - Gets the inertia from a factored matrix
9384 
9385   Collective
9386 
9387   Input Parameter:
9388 . mat - the matrix
9389 
9390   Output Parameters:
9391 + nneg  - number of negative eigenvalues
9392 . nzero - number of zero eigenvalues
9393 - npos  - number of positive eigenvalues
9394 
9395   Level: advanced
9396 
9397   Note:
9398   Matrix must have been factored by `MatCholeskyFactor()`
9399 
9400 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9401 @*/
9402 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9403 {
9404   PetscFunctionBegin;
9405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9406   PetscValidType(mat, 1);
9407   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9408   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9409   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9410   PetscFunctionReturn(PETSC_SUCCESS);
9411 }
9412 
9413 /*@C
9414   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9415 
9416   Neighbor-wise Collective
9417 
9418   Input Parameters:
9419 + mat - the factored matrix obtained with `MatGetFactor()`
9420 - b   - the right-hand-side vectors
9421 
9422   Output Parameter:
9423 . x - the result vectors
9424 
9425   Level: developer
9426 
9427   Note:
9428   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9429   call `MatSolves`(A,x,x).
9430 
9431 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9432 @*/
9433 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9434 {
9435   PetscFunctionBegin;
9436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9437   PetscValidType(mat, 1);
9438   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9439   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9440   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9441 
9442   MatCheckPreallocated(mat, 1);
9443   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9444   PetscUseTypeMethod(mat, solves, b, x);
9445   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9446   PetscFunctionReturn(PETSC_SUCCESS);
9447 }
9448 
9449 /*@
9450   MatIsSymmetric - Test whether a matrix is symmetric
9451 
9452   Collective
9453 
9454   Input Parameters:
9455 + A   - the matrix to test
9456 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9457 
9458   Output Parameter:
9459 . flg - the result
9460 
9461   Level: intermediate
9462 
9463   Notes:
9464   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9465 
9466   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9467 
9468   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9469   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9470 
9471 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9472           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9473 @*/
9474 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9475 {
9476   PetscFunctionBegin;
9477   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9478   PetscAssertPointer(flg, 3);
9479   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9480   else {
9481     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9482     else PetscCall(MatIsTranspose(A, A, tol, flg));
9483     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9484   }
9485   PetscFunctionReturn(PETSC_SUCCESS);
9486 }
9487 
9488 /*@
9489   MatIsHermitian - Test whether a matrix is Hermitian
9490 
9491   Collective
9492 
9493   Input Parameters:
9494 + A   - the matrix to test
9495 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9496 
9497   Output Parameter:
9498 . flg - the result
9499 
9500   Level: intermediate
9501 
9502   Notes:
9503   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9504 
9505   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9506 
9507   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9508   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9509 
9510 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9511           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9512 @*/
9513 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9514 {
9515   PetscFunctionBegin;
9516   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9517   PetscAssertPointer(flg, 3);
9518   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9519   else {
9520     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9521     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9522     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9523   }
9524   PetscFunctionReturn(PETSC_SUCCESS);
9525 }
9526 
9527 /*@
9528   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9529 
9530   Not Collective
9531 
9532   Input Parameter:
9533 . A - the matrix to check
9534 
9535   Output Parameters:
9536 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9537 - flg - the result (only valid if set is `PETSC_TRUE`)
9538 
9539   Level: advanced
9540 
9541   Notes:
9542   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9543   if you want it explicitly checked
9544 
9545   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9546   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9547 
9548 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9549 @*/
9550 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9551 {
9552   PetscFunctionBegin;
9553   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9554   PetscAssertPointer(set, 2);
9555   PetscAssertPointer(flg, 3);
9556   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9557     *set = PETSC_TRUE;
9558     *flg = PetscBool3ToBool(A->symmetric);
9559   } else {
9560     *set = PETSC_FALSE;
9561   }
9562   PetscFunctionReturn(PETSC_SUCCESS);
9563 }
9564 
9565 /*@
9566   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9567 
9568   Not Collective
9569 
9570   Input Parameter:
9571 . A - the matrix to check
9572 
9573   Output Parameters:
9574 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9575 - flg - the result (only valid if set is `PETSC_TRUE`)
9576 
9577   Level: advanced
9578 
9579   Notes:
9580   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9581 
9582   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9583   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9584 
9585 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9586 @*/
9587 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9588 {
9589   PetscFunctionBegin;
9590   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9591   PetscAssertPointer(set, 2);
9592   PetscAssertPointer(flg, 3);
9593   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9594     *set = PETSC_TRUE;
9595     *flg = PetscBool3ToBool(A->spd);
9596   } else {
9597     *set = PETSC_FALSE;
9598   }
9599   PetscFunctionReturn(PETSC_SUCCESS);
9600 }
9601 
9602 /*@
9603   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9604 
9605   Not Collective
9606 
9607   Input Parameter:
9608 . A - the matrix to check
9609 
9610   Output Parameters:
9611 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9612 - flg - the result (only valid if set is `PETSC_TRUE`)
9613 
9614   Level: advanced
9615 
9616   Notes:
9617   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9618   if you want it explicitly checked
9619 
9620   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9621   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9622 
9623 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9624 @*/
9625 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9626 {
9627   PetscFunctionBegin;
9628   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9629   PetscAssertPointer(set, 2);
9630   PetscAssertPointer(flg, 3);
9631   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9632     *set = PETSC_TRUE;
9633     *flg = PetscBool3ToBool(A->hermitian);
9634   } else {
9635     *set = PETSC_FALSE;
9636   }
9637   PetscFunctionReturn(PETSC_SUCCESS);
9638 }
9639 
9640 /*@
9641   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9642 
9643   Collective
9644 
9645   Input Parameter:
9646 . A - the matrix to test
9647 
9648   Output Parameter:
9649 . flg - the result
9650 
9651   Level: intermediate
9652 
9653   Notes:
9654   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9655 
9656   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
9657   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9658 
9659 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9660 @*/
9661 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9662 {
9663   PetscFunctionBegin;
9664   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9665   PetscAssertPointer(flg, 2);
9666   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9667     *flg = PetscBool3ToBool(A->structurally_symmetric);
9668   } else {
9669     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9670     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9671   }
9672   PetscFunctionReturn(PETSC_SUCCESS);
9673 }
9674 
9675 /*@
9676   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9677 
9678   Not Collective
9679 
9680   Input Parameter:
9681 . A - the matrix to check
9682 
9683   Output Parameters:
9684 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9685 - flg - the result (only valid if set is PETSC_TRUE)
9686 
9687   Level: advanced
9688 
9689   Notes:
9690   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
9691   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9692 
9693   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9694 
9695 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9696 @*/
9697 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9698 {
9699   PetscFunctionBegin;
9700   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9701   PetscAssertPointer(set, 2);
9702   PetscAssertPointer(flg, 3);
9703   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9704     *set = PETSC_TRUE;
9705     *flg = PetscBool3ToBool(A->structurally_symmetric);
9706   } else {
9707     *set = PETSC_FALSE;
9708   }
9709   PetscFunctionReturn(PETSC_SUCCESS);
9710 }
9711 
9712 /*@
9713   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9714   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9715 
9716   Not Collective
9717 
9718   Input Parameter:
9719 . mat - the matrix
9720 
9721   Output Parameters:
9722 + nstash    - the size of the stash
9723 . reallocs  - the number of additional mallocs incurred.
9724 . bnstash   - the size of the block stash
9725 - breallocs - the number of additional mallocs incurred.in the block stash
9726 
9727   Level: advanced
9728 
9729 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9730 @*/
9731 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9732 {
9733   PetscFunctionBegin;
9734   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9735   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9736   PetscFunctionReturn(PETSC_SUCCESS);
9737 }
9738 
9739 /*@
9740   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9741   parallel layout, `PetscLayout` for rows and columns
9742 
9743   Collective
9744 
9745   Input Parameter:
9746 . mat - the matrix
9747 
9748   Output Parameters:
9749 + right - (optional) vector that the matrix can be multiplied against
9750 - left  - (optional) vector that the matrix vector product can be stored in
9751 
9752   Level: advanced
9753 
9754   Notes:
9755   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()`.
9756 
9757   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9758 
9759 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9760 @*/
9761 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9762 {
9763   PetscFunctionBegin;
9764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9765   PetscValidType(mat, 1);
9766   if (mat->ops->getvecs) {
9767     PetscUseTypeMethod(mat, getvecs, right, left);
9768   } else {
9769     if (right) {
9770       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9771       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9772       PetscCall(VecSetType(*right, mat->defaultvectype));
9773 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9774       if (mat->boundtocpu && mat->bindingpropagates) {
9775         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9776         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9777       }
9778 #endif
9779     }
9780     if (left) {
9781       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9782       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9783       PetscCall(VecSetType(*left, mat->defaultvectype));
9784 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9785       if (mat->boundtocpu && mat->bindingpropagates) {
9786         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9787         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9788       }
9789 #endif
9790     }
9791   }
9792   PetscFunctionReturn(PETSC_SUCCESS);
9793 }
9794 
9795 /*@
9796   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9797   with default values.
9798 
9799   Not Collective
9800 
9801   Input Parameter:
9802 . info - the `MatFactorInfo` data structure
9803 
9804   Level: developer
9805 
9806   Notes:
9807   The solvers are generally used through the `KSP` and `PC` objects, for example
9808   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9809 
9810   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9811 
9812 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9813 @*/
9814 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9815 {
9816   PetscFunctionBegin;
9817   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9818   PetscFunctionReturn(PETSC_SUCCESS);
9819 }
9820 
9821 /*@
9822   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9823 
9824   Collective
9825 
9826   Input Parameters:
9827 + mat - the factored matrix
9828 - is  - the index set defining the Schur indices (0-based)
9829 
9830   Level: advanced
9831 
9832   Notes:
9833   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9834 
9835   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9836 
9837   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9838 
9839 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9840           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9841 @*/
9842 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9843 {
9844   PetscErrorCode (*f)(Mat, IS);
9845 
9846   PetscFunctionBegin;
9847   PetscValidType(mat, 1);
9848   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9849   PetscValidType(is, 2);
9850   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9851   PetscCheckSameComm(mat, 1, is, 2);
9852   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9853   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9854   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9855   PetscCall(MatDestroy(&mat->schur));
9856   PetscCall((*f)(mat, is));
9857   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9858   PetscFunctionReturn(PETSC_SUCCESS);
9859 }
9860 
9861 /*@
9862   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9863 
9864   Logically Collective
9865 
9866   Input Parameters:
9867 + F      - the factored matrix obtained by calling `MatGetFactor()`
9868 . S      - location where to return the Schur complement, can be `NULL`
9869 - status - the status of the Schur complement matrix, can be `NULL`
9870 
9871   Level: advanced
9872 
9873   Notes:
9874   You must call `MatFactorSetSchurIS()` before calling this routine.
9875 
9876   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9877 
9878   The routine provides a copy of the Schur matrix stored within the solver data structures.
9879   The caller must destroy the object when it is no longer needed.
9880   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9881 
9882   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)
9883 
9884   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9885 
9886   Developer Note:
9887   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9888   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9889 
9890 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9891 @*/
9892 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9893 {
9894   PetscFunctionBegin;
9895   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9896   if (S) PetscAssertPointer(S, 2);
9897   if (status) PetscAssertPointer(status, 3);
9898   if (S) {
9899     PetscErrorCode (*f)(Mat, Mat *);
9900 
9901     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9902     if (f) {
9903       PetscCall((*f)(F, S));
9904     } else {
9905       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9906     }
9907   }
9908   if (status) *status = F->schur_status;
9909   PetscFunctionReturn(PETSC_SUCCESS);
9910 }
9911 
9912 /*@
9913   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9914 
9915   Logically Collective
9916 
9917   Input Parameters:
9918 + F      - the factored matrix obtained by calling `MatGetFactor()`
9919 . S      - location where to return the Schur complement, can be `NULL`
9920 - status - the status of the Schur complement matrix, can be `NULL`
9921 
9922   Level: advanced
9923 
9924   Notes:
9925   You must call `MatFactorSetSchurIS()` before calling this routine.
9926 
9927   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9928 
9929   The routine returns a the Schur Complement stored within the data structures of the solver.
9930 
9931   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9932 
9933   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9934 
9935   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9936 
9937   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9938 
9939 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9940 @*/
9941 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9942 {
9943   PetscFunctionBegin;
9944   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9945   if (S) {
9946     PetscAssertPointer(S, 2);
9947     *S = F->schur;
9948   }
9949   if (status) {
9950     PetscAssertPointer(status, 3);
9951     *status = F->schur_status;
9952   }
9953   PetscFunctionReturn(PETSC_SUCCESS);
9954 }
9955 
9956 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9957 {
9958   Mat S = F->schur;
9959 
9960   PetscFunctionBegin;
9961   switch (F->schur_status) {
9962   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9963   case MAT_FACTOR_SCHUR_INVERTED:
9964     if (S) {
9965       S->ops->solve             = NULL;
9966       S->ops->matsolve          = NULL;
9967       S->ops->solvetranspose    = NULL;
9968       S->ops->matsolvetranspose = NULL;
9969       S->ops->solveadd          = NULL;
9970       S->ops->solvetransposeadd = NULL;
9971       S->factortype             = MAT_FACTOR_NONE;
9972       PetscCall(PetscFree(S->solvertype));
9973     }
9974   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9975     break;
9976   default:
9977     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9978   }
9979   PetscFunctionReturn(PETSC_SUCCESS);
9980 }
9981 
9982 /*@
9983   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9984 
9985   Logically Collective
9986 
9987   Input Parameters:
9988 + F      - the factored matrix obtained by calling `MatGetFactor()`
9989 . S      - location where the Schur complement is stored
9990 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9991 
9992   Level: advanced
9993 
9994 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9995 @*/
9996 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9997 {
9998   PetscFunctionBegin;
9999   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10000   if (S) {
10001     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
10002     *S = NULL;
10003   }
10004   F->schur_status = status;
10005   PetscCall(MatFactorUpdateSchurStatus_Private(F));
10006   PetscFunctionReturn(PETSC_SUCCESS);
10007 }
10008 
10009 /*@
10010   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
10011 
10012   Logically Collective
10013 
10014   Input Parameters:
10015 + F   - the factored matrix obtained by calling `MatGetFactor()`
10016 . rhs - location where the right-hand side of the Schur complement system is stored
10017 - sol - location where the solution of the Schur complement system has to be returned
10018 
10019   Level: advanced
10020 
10021   Notes:
10022   The sizes of the vectors should match the size of the Schur complement
10023 
10024   Must be called after `MatFactorSetSchurIS()`
10025 
10026 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
10027 @*/
10028 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
10029 {
10030   PetscFunctionBegin;
10031   PetscValidType(F, 1);
10032   PetscValidType(rhs, 2);
10033   PetscValidType(sol, 3);
10034   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10035   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10036   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10037   PetscCheckSameComm(F, 1, rhs, 2);
10038   PetscCheckSameComm(F, 1, sol, 3);
10039   PetscCall(MatFactorFactorizeSchurComplement(F));
10040   switch (F->schur_status) {
10041   case MAT_FACTOR_SCHUR_FACTORED:
10042     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
10043     break;
10044   case MAT_FACTOR_SCHUR_INVERTED:
10045     PetscCall(MatMultTranspose(F->schur, rhs, sol));
10046     break;
10047   default:
10048     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10049   }
10050   PetscFunctionReturn(PETSC_SUCCESS);
10051 }
10052 
10053 /*@
10054   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
10055 
10056   Logically Collective
10057 
10058   Input Parameters:
10059 + F   - the factored matrix obtained by calling `MatGetFactor()`
10060 . rhs - location where the right-hand side of the Schur complement system is stored
10061 - sol - location where the solution of the Schur complement system has to be returned
10062 
10063   Level: advanced
10064 
10065   Notes:
10066   The sizes of the vectors should match the size of the Schur complement
10067 
10068   Must be called after `MatFactorSetSchurIS()`
10069 
10070 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
10071 @*/
10072 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
10073 {
10074   PetscFunctionBegin;
10075   PetscValidType(F, 1);
10076   PetscValidType(rhs, 2);
10077   PetscValidType(sol, 3);
10078   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10079   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10080   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10081   PetscCheckSameComm(F, 1, rhs, 2);
10082   PetscCheckSameComm(F, 1, sol, 3);
10083   PetscCall(MatFactorFactorizeSchurComplement(F));
10084   switch (F->schur_status) {
10085   case MAT_FACTOR_SCHUR_FACTORED:
10086     PetscCall(MatSolve(F->schur, rhs, sol));
10087     break;
10088   case MAT_FACTOR_SCHUR_INVERTED:
10089     PetscCall(MatMult(F->schur, rhs, sol));
10090     break;
10091   default:
10092     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10093   }
10094   PetscFunctionReturn(PETSC_SUCCESS);
10095 }
10096 
10097 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10098 #if PetscDefined(HAVE_CUDA)
10099 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10100 #endif
10101 
10102 /* Schur status updated in the interface */
10103 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10104 {
10105   Mat S = F->schur;
10106 
10107   PetscFunctionBegin;
10108   if (S) {
10109     PetscMPIInt size;
10110     PetscBool   isdense, isdensecuda;
10111 
10112     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10113     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10114     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10115     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10116     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10117     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10118     if (isdense) {
10119       PetscCall(MatSeqDenseInvertFactors_Private(S));
10120     } else if (isdensecuda) {
10121 #if defined(PETSC_HAVE_CUDA)
10122       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10123 #endif
10124     }
10125     // HIP??????????????
10126     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10127   }
10128   PetscFunctionReturn(PETSC_SUCCESS);
10129 }
10130 
10131 /*@
10132   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10133 
10134   Logically Collective
10135 
10136   Input Parameter:
10137 . F - the factored matrix obtained by calling `MatGetFactor()`
10138 
10139   Level: advanced
10140 
10141   Notes:
10142   Must be called after `MatFactorSetSchurIS()`.
10143 
10144   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10145 
10146 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10147 @*/
10148 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10149 {
10150   PetscFunctionBegin;
10151   PetscValidType(F, 1);
10152   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10153   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10154   PetscCall(MatFactorFactorizeSchurComplement(F));
10155   PetscCall(MatFactorInvertSchurComplement_Private(F));
10156   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10157   PetscFunctionReturn(PETSC_SUCCESS);
10158 }
10159 
10160 /*@
10161   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10162 
10163   Logically Collective
10164 
10165   Input Parameter:
10166 . F - the factored matrix obtained by calling `MatGetFactor()`
10167 
10168   Level: advanced
10169 
10170   Note:
10171   Must be called after `MatFactorSetSchurIS()`
10172 
10173 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10174 @*/
10175 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10176 {
10177   MatFactorInfo info;
10178 
10179   PetscFunctionBegin;
10180   PetscValidType(F, 1);
10181   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10182   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10183   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10184   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10185   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10186     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10187   } else {
10188     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10189   }
10190   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10191   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10192   PetscFunctionReturn(PETSC_SUCCESS);
10193 }
10194 
10195 /*@
10196   MatPtAP - Creates the matrix product $C = P^T * A * P$
10197 
10198   Neighbor-wise Collective
10199 
10200   Input Parameters:
10201 + A     - the matrix
10202 . P     - the projection matrix
10203 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10204 - 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
10205           if the result is a dense matrix this is irrelevant
10206 
10207   Output Parameter:
10208 . C - the product matrix
10209 
10210   Level: intermediate
10211 
10212   Notes:
10213   C will be created and must be destroyed by the user with `MatDestroy()`.
10214 
10215   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10216 
10217   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10218 
10219   Developer Note:
10220   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10221 
10222 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10223 @*/
10224 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10225 {
10226   PetscFunctionBegin;
10227   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10228   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10229 
10230   if (scall == MAT_INITIAL_MATRIX) {
10231     PetscCall(MatProductCreate(A, P, NULL, C));
10232     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10233     PetscCall(MatProductSetAlgorithm(*C, "default"));
10234     PetscCall(MatProductSetFill(*C, fill));
10235 
10236     (*C)->product->api_user = PETSC_TRUE;
10237     PetscCall(MatProductSetFromOptions(*C));
10238     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);
10239     PetscCall(MatProductSymbolic(*C));
10240   } else { /* scall == MAT_REUSE_MATRIX */
10241     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10242   }
10243 
10244   PetscCall(MatProductNumeric(*C));
10245   (*C)->symmetric = A->symmetric;
10246   (*C)->spd       = A->spd;
10247   PetscFunctionReturn(PETSC_SUCCESS);
10248 }
10249 
10250 /*@
10251   MatRARt - Creates the matrix product $C = R * A * R^T$
10252 
10253   Neighbor-wise Collective
10254 
10255   Input Parameters:
10256 + A     - the matrix
10257 . R     - the projection matrix
10258 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10259 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10260           if the result is a dense matrix this is irrelevant
10261 
10262   Output Parameter:
10263 . C - the product matrix
10264 
10265   Level: intermediate
10266 
10267   Notes:
10268   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10269 
10270   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10271 
10272   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10273   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10274   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10275   We recommend using `MatPtAP()` when possible.
10276 
10277   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10278 
10279 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10280 @*/
10281 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10282 {
10283   PetscFunctionBegin;
10284   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10285   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10286 
10287   if (scall == MAT_INITIAL_MATRIX) {
10288     PetscCall(MatProductCreate(A, R, NULL, C));
10289     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10290     PetscCall(MatProductSetAlgorithm(*C, "default"));
10291     PetscCall(MatProductSetFill(*C, fill));
10292 
10293     (*C)->product->api_user = PETSC_TRUE;
10294     PetscCall(MatProductSetFromOptions(*C));
10295     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);
10296     PetscCall(MatProductSymbolic(*C));
10297   } else { /* scall == MAT_REUSE_MATRIX */
10298     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10299   }
10300 
10301   PetscCall(MatProductNumeric(*C));
10302   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10303   PetscFunctionReturn(PETSC_SUCCESS);
10304 }
10305 
10306 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10307 {
10308   PetscBool flg = PETSC_TRUE;
10309 
10310   PetscFunctionBegin;
10311   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10312   if (scall == MAT_INITIAL_MATRIX) {
10313     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10314     PetscCall(MatProductCreate(A, B, NULL, C));
10315     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10316     PetscCall(MatProductSetFill(*C, fill));
10317   } else { /* scall == MAT_REUSE_MATRIX */
10318     Mat_Product *product = (*C)->product;
10319 
10320     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10321     if (flg && product && product->type != ptype) {
10322       PetscCall(MatProductClear(*C));
10323       product = NULL;
10324     }
10325     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10326     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10327       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10328       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10329       product        = (*C)->product;
10330       product->fill  = fill;
10331       product->clear = PETSC_TRUE;
10332     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10333       flg = PETSC_FALSE;
10334       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10335     }
10336   }
10337   if (flg) {
10338     (*C)->product->api_user = PETSC_TRUE;
10339     PetscCall(MatProductSetType(*C, ptype));
10340     PetscCall(MatProductSetFromOptions(*C));
10341     PetscCall(MatProductSymbolic(*C));
10342   }
10343   PetscCall(MatProductNumeric(*C));
10344   PetscFunctionReturn(PETSC_SUCCESS);
10345 }
10346 
10347 /*@
10348   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10349 
10350   Neighbor-wise Collective
10351 
10352   Input Parameters:
10353 + A     - the left matrix
10354 . B     - the right matrix
10355 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10356 - 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
10357           if the result is a dense matrix this is irrelevant
10358 
10359   Output Parameter:
10360 . C - the product matrix
10361 
10362   Notes:
10363   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10364 
10365   `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
10366   call to this function with `MAT_INITIAL_MATRIX`.
10367 
10368   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10369 
10370   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`,
10371   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10372 
10373   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10374 
10375   Example of Usage:
10376 .vb
10377      MatProductCreate(A,B,NULL,&C);
10378      MatProductSetType(C,MATPRODUCT_AB);
10379      MatProductSymbolic(C);
10380      MatProductNumeric(C); // compute C=A * B
10381      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10382      MatProductNumeric(C);
10383      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10384      MatProductNumeric(C);
10385 .ve
10386 
10387   Level: intermediate
10388 
10389 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10390 @*/
10391 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10392 {
10393   PetscFunctionBegin;
10394   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10395   PetscFunctionReturn(PETSC_SUCCESS);
10396 }
10397 
10398 /*@
10399   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10400 
10401   Neighbor-wise Collective
10402 
10403   Input Parameters:
10404 + A     - the left matrix
10405 . B     - the right matrix
10406 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10407 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10408 
10409   Output Parameter:
10410 . C - the product matrix
10411 
10412   Options Database Key:
10413 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10414               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10415               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10416 
10417   Level: intermediate
10418 
10419   Notes:
10420   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10421 
10422   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10423 
10424   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10425   actually needed.
10426 
10427   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10428   and for pairs of `MATMPIDENSE` matrices.
10429 
10430   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10431 
10432   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10433 
10434 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10435 @*/
10436 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10437 {
10438   PetscFunctionBegin;
10439   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10440   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10441   PetscFunctionReturn(PETSC_SUCCESS);
10442 }
10443 
10444 /*@
10445   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10446 
10447   Neighbor-wise Collective
10448 
10449   Input Parameters:
10450 + A     - the left matrix
10451 . B     - the right matrix
10452 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10453 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10454 
10455   Output Parameter:
10456 . C - the product matrix
10457 
10458   Level: intermediate
10459 
10460   Notes:
10461   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10462 
10463   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10464 
10465   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10466 
10467   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10468   actually needed.
10469 
10470   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10471   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10472 
10473   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10474 
10475 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10476 @*/
10477 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10478 {
10479   PetscFunctionBegin;
10480   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10481   PetscFunctionReturn(PETSC_SUCCESS);
10482 }
10483 
10484 /*@
10485   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10486 
10487   Neighbor-wise Collective
10488 
10489   Input Parameters:
10490 + A     - the left matrix
10491 . B     - the middle matrix
10492 . C     - the right matrix
10493 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10494 - 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
10495           if the result is a dense matrix this is irrelevant
10496 
10497   Output Parameter:
10498 . D - the product matrix
10499 
10500   Level: intermediate
10501 
10502   Notes:
10503   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10504 
10505   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10506 
10507   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10508 
10509   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10510   actually needed.
10511 
10512   If you have many matrices with the same non-zero structure to multiply, you
10513   should use `MAT_REUSE_MATRIX` in all calls but the first
10514 
10515   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10516 
10517 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10518 @*/
10519 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10520 {
10521   PetscFunctionBegin;
10522   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10523   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10524 
10525   if (scall == MAT_INITIAL_MATRIX) {
10526     PetscCall(MatProductCreate(A, B, C, D));
10527     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10528     PetscCall(MatProductSetAlgorithm(*D, "default"));
10529     PetscCall(MatProductSetFill(*D, fill));
10530 
10531     (*D)->product->api_user = PETSC_TRUE;
10532     PetscCall(MatProductSetFromOptions(*D));
10533     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,
10534                ((PetscObject)C)->type_name);
10535     PetscCall(MatProductSymbolic(*D));
10536   } else { /* user may change input matrices when REUSE */
10537     PetscCall(MatProductReplaceMats(A, B, C, *D));
10538   }
10539   PetscCall(MatProductNumeric(*D));
10540   PetscFunctionReturn(PETSC_SUCCESS);
10541 }
10542 
10543 /*@
10544   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10545 
10546   Collective
10547 
10548   Input Parameters:
10549 + mat      - the matrix
10550 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10551 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10552 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10553 
10554   Output Parameter:
10555 . matredundant - redundant matrix
10556 
10557   Level: advanced
10558 
10559   Notes:
10560   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10561   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10562 
10563   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10564   calling it.
10565 
10566   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10567 
10568 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10569 @*/
10570 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10571 {
10572   MPI_Comm       comm;
10573   PetscMPIInt    size;
10574   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10575   Mat_Redundant *redund     = NULL;
10576   PetscSubcomm   psubcomm   = NULL;
10577   MPI_Comm       subcomm_in = subcomm;
10578   Mat           *matseq;
10579   IS             isrow, iscol;
10580   PetscBool      newsubcomm = PETSC_FALSE;
10581 
10582   PetscFunctionBegin;
10583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10584   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10585     PetscAssertPointer(*matredundant, 5);
10586     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10587   }
10588 
10589   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10590   if (size == 1 || nsubcomm == 1) {
10591     if (reuse == MAT_INITIAL_MATRIX) {
10592       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10593     } else {
10594       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");
10595       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10596     }
10597     PetscFunctionReturn(PETSC_SUCCESS);
10598   }
10599 
10600   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10601   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10602   MatCheckPreallocated(mat, 1);
10603 
10604   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10605   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10606     /* create psubcomm, then get subcomm */
10607     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10608     PetscCallMPI(MPI_Comm_size(comm, &size));
10609     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10610 
10611     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10612     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10613     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10614     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10615     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10616     newsubcomm = PETSC_TRUE;
10617     PetscCall(PetscSubcommDestroy(&psubcomm));
10618   }
10619 
10620   /* get isrow, iscol and a local sequential matrix matseq[0] */
10621   if (reuse == MAT_INITIAL_MATRIX) {
10622     mloc_sub = PETSC_DECIDE;
10623     nloc_sub = PETSC_DECIDE;
10624     if (bs < 1) {
10625       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10626       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10627     } else {
10628       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10629       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10630     }
10631     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10632     rstart = rend - mloc_sub;
10633     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10634     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10635     PetscCall(ISSetIdentity(iscol));
10636   } else { /* reuse == MAT_REUSE_MATRIX */
10637     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");
10638     /* retrieve subcomm */
10639     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10640     redund = (*matredundant)->redundant;
10641     isrow  = redund->isrow;
10642     iscol  = redund->iscol;
10643     matseq = redund->matseq;
10644   }
10645   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10646 
10647   /* get matredundant over subcomm */
10648   if (reuse == MAT_INITIAL_MATRIX) {
10649     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10650 
10651     /* create a supporting struct and attach it to C for reuse */
10652     PetscCall(PetscNew(&redund));
10653     (*matredundant)->redundant = redund;
10654     redund->isrow              = isrow;
10655     redund->iscol              = iscol;
10656     redund->matseq             = matseq;
10657     if (newsubcomm) {
10658       redund->subcomm = subcomm;
10659     } else {
10660       redund->subcomm = MPI_COMM_NULL;
10661     }
10662   } else {
10663     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10664   }
10665 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10666   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10667     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10668     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10669   }
10670 #endif
10671   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10672   PetscFunctionReturn(PETSC_SUCCESS);
10673 }
10674 
10675 /*@C
10676   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10677   a given `Mat`. Each submatrix can span multiple procs.
10678 
10679   Collective
10680 
10681   Input Parameters:
10682 + mat     - the matrix
10683 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10684 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10685 
10686   Output Parameter:
10687 . subMat - parallel sub-matrices each spanning a given `subcomm`
10688 
10689   Level: advanced
10690 
10691   Notes:
10692   The submatrix partition across processors is dictated by `subComm` a
10693   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10694   is not restricted to be grouped with consecutive original MPI processes.
10695 
10696   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10697   map directly to the layout of the original matrix [wrt the local
10698   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10699   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10700   the `subMat`. However the offDiagMat looses some columns - and this is
10701   reconstructed with `MatSetValues()`
10702 
10703   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10704 
10705 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10706 @*/
10707 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10708 {
10709   PetscMPIInt commsize, subCommSize;
10710 
10711   PetscFunctionBegin;
10712   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10713   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10714   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10715 
10716   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");
10717   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10718   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10719   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10720   PetscFunctionReturn(PETSC_SUCCESS);
10721 }
10722 
10723 /*@
10724   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10725 
10726   Not Collective
10727 
10728   Input Parameters:
10729 + mat   - matrix to extract local submatrix from
10730 . isrow - local row indices for submatrix
10731 - iscol - local column indices for submatrix
10732 
10733   Output Parameter:
10734 . submat - the submatrix
10735 
10736   Level: intermediate
10737 
10738   Notes:
10739   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10740 
10741   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10742   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10743 
10744   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10745   `MatSetValuesBlockedLocal()` will also be implemented.
10746 
10747   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10748   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10749 
10750 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10751 @*/
10752 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10753 {
10754   PetscFunctionBegin;
10755   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10756   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10757   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10758   PetscCheckSameComm(isrow, 2, iscol, 3);
10759   PetscAssertPointer(submat, 4);
10760   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10761 
10762   if (mat->ops->getlocalsubmatrix) {
10763     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10764   } else {
10765     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10766   }
10767   PetscFunctionReturn(PETSC_SUCCESS);
10768 }
10769 
10770 /*@
10771   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10772 
10773   Not Collective
10774 
10775   Input Parameters:
10776 + mat    - matrix to extract local submatrix from
10777 . isrow  - local row indices for submatrix
10778 . iscol  - local column indices for submatrix
10779 - submat - the submatrix
10780 
10781   Level: intermediate
10782 
10783 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10784 @*/
10785 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10786 {
10787   PetscFunctionBegin;
10788   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10789   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10790   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10791   PetscCheckSameComm(isrow, 2, iscol, 3);
10792   PetscAssertPointer(submat, 4);
10793   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10794 
10795   if (mat->ops->restorelocalsubmatrix) {
10796     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10797   } else {
10798     PetscCall(MatDestroy(submat));
10799   }
10800   *submat = NULL;
10801   PetscFunctionReturn(PETSC_SUCCESS);
10802 }
10803 
10804 /*@
10805   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10806 
10807   Collective
10808 
10809   Input Parameter:
10810 . mat - the matrix
10811 
10812   Output Parameter:
10813 . is - if any rows have zero diagonals this contains the list of them
10814 
10815   Level: developer
10816 
10817 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10818 @*/
10819 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10820 {
10821   PetscFunctionBegin;
10822   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10823   PetscValidType(mat, 1);
10824   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10825   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10826 
10827   if (!mat->ops->findzerodiagonals) {
10828     Vec                diag;
10829     const PetscScalar *a;
10830     PetscInt          *rows;
10831     PetscInt           rStart, rEnd, r, nrow = 0;
10832 
10833     PetscCall(MatCreateVecs(mat, &diag, NULL));
10834     PetscCall(MatGetDiagonal(mat, diag));
10835     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10836     PetscCall(VecGetArrayRead(diag, &a));
10837     for (r = 0; r < rEnd - rStart; ++r)
10838       if (a[r] == 0.0) ++nrow;
10839     PetscCall(PetscMalloc1(nrow, &rows));
10840     nrow = 0;
10841     for (r = 0; r < rEnd - rStart; ++r)
10842       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10843     PetscCall(VecRestoreArrayRead(diag, &a));
10844     PetscCall(VecDestroy(&diag));
10845     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10846   } else {
10847     PetscUseTypeMethod(mat, findzerodiagonals, is);
10848   }
10849   PetscFunctionReturn(PETSC_SUCCESS);
10850 }
10851 
10852 /*@
10853   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10854 
10855   Collective
10856 
10857   Input Parameter:
10858 . mat - the matrix
10859 
10860   Output Parameter:
10861 . is - contains the list of rows with off block diagonal entries
10862 
10863   Level: developer
10864 
10865 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10866 @*/
10867 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10868 {
10869   PetscFunctionBegin;
10870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10871   PetscValidType(mat, 1);
10872   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10873   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10874 
10875   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10876   PetscFunctionReturn(PETSC_SUCCESS);
10877 }
10878 
10879 /*@C
10880   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10881 
10882   Collective; No Fortran Support
10883 
10884   Input Parameter:
10885 . mat - the matrix
10886 
10887   Output Parameter:
10888 . values - the block inverses in column major order (FORTRAN-like)
10889 
10890   Level: advanced
10891 
10892   Notes:
10893   The size of the blocks is determined by the block size of the matrix.
10894 
10895   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10896 
10897   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10898 
10899 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10900 @*/
10901 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10902 {
10903   PetscFunctionBegin;
10904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10905   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10906   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10907   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10908   PetscFunctionReturn(PETSC_SUCCESS);
10909 }
10910 
10911 /*@
10912   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10913 
10914   Collective; No Fortran Support
10915 
10916   Input Parameters:
10917 + mat     - the matrix
10918 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10919 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10920 
10921   Output Parameter:
10922 . values - the block inverses in column major order (FORTRAN-like)
10923 
10924   Level: advanced
10925 
10926   Notes:
10927   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10928 
10929   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10930 
10931 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10932 @*/
10933 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10934 {
10935   PetscFunctionBegin;
10936   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10937   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10938   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10939   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10940   PetscFunctionReturn(PETSC_SUCCESS);
10941 }
10942 
10943 /*@
10944   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10945 
10946   Collective
10947 
10948   Input Parameters:
10949 + A - the matrix
10950 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10951 
10952   Level: advanced
10953 
10954   Note:
10955   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10956 
10957 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10958 @*/
10959 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10960 {
10961   const PetscScalar *vals;
10962   PetscInt          *dnnz;
10963   PetscInt           m, rstart, rend, bs, i, j;
10964 
10965   PetscFunctionBegin;
10966   PetscCall(MatInvertBlockDiagonal(A, &vals));
10967   PetscCall(MatGetBlockSize(A, &bs));
10968   PetscCall(MatGetLocalSize(A, &m, NULL));
10969   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10970   PetscCall(PetscMalloc1(m / bs, &dnnz));
10971   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10972   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10973   PetscCall(PetscFree(dnnz));
10974   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10975   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10976   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10977   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10978   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10979   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10980   PetscFunctionReturn(PETSC_SUCCESS);
10981 }
10982 
10983 /*@
10984   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10985   via `MatTransposeColoringCreate()`.
10986 
10987   Collective
10988 
10989   Input Parameter:
10990 . c - coloring context
10991 
10992   Level: intermediate
10993 
10994 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10995 @*/
10996 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10997 {
10998   MatTransposeColoring matcolor = *c;
10999 
11000   PetscFunctionBegin;
11001   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
11002   if (--((PetscObject)matcolor)->refct > 0) {
11003     matcolor = NULL;
11004     PetscFunctionReturn(PETSC_SUCCESS);
11005   }
11006 
11007   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
11008   PetscCall(PetscFree(matcolor->rows));
11009   PetscCall(PetscFree(matcolor->den2sp));
11010   PetscCall(PetscFree(matcolor->colorforcol));
11011   PetscCall(PetscFree(matcolor->columns));
11012   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
11013   PetscCall(PetscHeaderDestroy(c));
11014   PetscFunctionReturn(PETSC_SUCCESS);
11015 }
11016 
11017 /*@
11018   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
11019   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
11020   `MatTransposeColoring` to sparse `B`.
11021 
11022   Collective
11023 
11024   Input Parameters:
11025 + coloring - coloring context created with `MatTransposeColoringCreate()`
11026 - B        - sparse matrix
11027 
11028   Output Parameter:
11029 . Btdense - dense matrix $B^T$
11030 
11031   Level: developer
11032 
11033   Note:
11034   These are used internally for some implementations of `MatRARt()`
11035 
11036 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
11037 @*/
11038 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
11039 {
11040   PetscFunctionBegin;
11041   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11042   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
11043   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
11044 
11045   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
11046   PetscFunctionReturn(PETSC_SUCCESS);
11047 }
11048 
11049 /*@
11050   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
11051   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
11052   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
11053   $C_{sp}$ from $C_{den}$.
11054 
11055   Collective
11056 
11057   Input Parameters:
11058 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
11059 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
11060 
11061   Output Parameter:
11062 . Csp - sparse matrix
11063 
11064   Level: developer
11065 
11066   Note:
11067   These are used internally for some implementations of `MatRARt()`
11068 
11069 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
11070 @*/
11071 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
11072 {
11073   PetscFunctionBegin;
11074   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11075   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
11076   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
11077 
11078   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
11079   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
11080   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
11081   PetscFunctionReturn(PETSC_SUCCESS);
11082 }
11083 
11084 /*@
11085   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
11086 
11087   Collective
11088 
11089   Input Parameters:
11090 + mat        - the matrix product C
11091 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
11092 
11093   Output Parameter:
11094 . color - the new coloring context
11095 
11096   Level: intermediate
11097 
11098 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11099           `MatTransColoringApplyDenToSp()`
11100 @*/
11101 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11102 {
11103   MatTransposeColoring c;
11104   MPI_Comm             comm;
11105 
11106   PetscFunctionBegin;
11107   PetscAssertPointer(color, 3);
11108 
11109   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11110   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11111   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11112   c->ctype = iscoloring->ctype;
11113   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11114   *color = c;
11115   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11116   PetscFunctionReturn(PETSC_SUCCESS);
11117 }
11118 
11119 /*@
11120   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11121   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11122 
11123   Not Collective
11124 
11125   Input Parameter:
11126 . mat - the matrix
11127 
11128   Output Parameter:
11129 . state - the current state
11130 
11131   Level: intermediate
11132 
11133   Notes:
11134   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11135   different matrices
11136 
11137   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11138 
11139   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11140 
11141 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11142 @*/
11143 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11144 {
11145   PetscFunctionBegin;
11146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11147   *state = mat->nonzerostate;
11148   PetscFunctionReturn(PETSC_SUCCESS);
11149 }
11150 
11151 /*@
11152   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11153   matrices from each processor
11154 
11155   Collective
11156 
11157   Input Parameters:
11158 + comm   - the communicators the parallel matrix will live on
11159 . seqmat - the input sequential matrices
11160 . n      - number of local columns (or `PETSC_DECIDE`)
11161 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11162 
11163   Output Parameter:
11164 . mpimat - the parallel matrix generated
11165 
11166   Level: developer
11167 
11168   Note:
11169   The number of columns of the matrix in EACH processor MUST be the same.
11170 
11171 .seealso: [](ch_matrices), `Mat`
11172 @*/
11173 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11174 {
11175   PetscMPIInt size;
11176 
11177   PetscFunctionBegin;
11178   PetscCallMPI(MPI_Comm_size(comm, &size));
11179   if (size == 1) {
11180     if (reuse == MAT_INITIAL_MATRIX) {
11181       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11182     } else {
11183       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11184     }
11185     PetscFunctionReturn(PETSC_SUCCESS);
11186   }
11187 
11188   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");
11189 
11190   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11191   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11192   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11193   PetscFunctionReturn(PETSC_SUCCESS);
11194 }
11195 
11196 /*@
11197   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11198 
11199   Collective
11200 
11201   Input Parameters:
11202 + A - the matrix to create subdomains from
11203 - N - requested number of subdomains
11204 
11205   Output Parameters:
11206 + n   - number of subdomains resulting on this MPI process
11207 - iss - `IS` list with indices of subdomains on this MPI process
11208 
11209   Level: advanced
11210 
11211   Note:
11212   The number of subdomains must be smaller than the communicator size
11213 
11214 .seealso: [](ch_matrices), `Mat`, `IS`
11215 @*/
11216 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11217 {
11218   MPI_Comm    comm, subcomm;
11219   PetscMPIInt size, rank, color;
11220   PetscInt    rstart, rend, k;
11221 
11222   PetscFunctionBegin;
11223   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11224   PetscCallMPI(MPI_Comm_size(comm, &size));
11225   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11226   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);
11227   *n    = 1;
11228   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
11229   color = rank / k;
11230   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11231   PetscCall(PetscMalloc1(1, iss));
11232   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11233   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11234   PetscCallMPI(MPI_Comm_free(&subcomm));
11235   PetscFunctionReturn(PETSC_SUCCESS);
11236 }
11237 
11238 /*@
11239   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11240 
11241   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11242   If they are not the same, uses `MatMatMatMult()`.
11243 
11244   Once the coarse grid problem is constructed, correct for interpolation operators
11245   that are not of full rank, which can legitimately happen in the case of non-nested
11246   geometric multigrid.
11247 
11248   Input Parameters:
11249 + restrct     - restriction operator
11250 . dA          - fine grid matrix
11251 . interpolate - interpolation operator
11252 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11253 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11254 
11255   Output Parameter:
11256 . A - the Galerkin coarse matrix
11257 
11258   Options Database Key:
11259 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11260 
11261   Level: developer
11262 
11263   Note:
11264   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11265 
11266 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11267 @*/
11268 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11269 {
11270   IS  zerorows;
11271   Vec diag;
11272 
11273   PetscFunctionBegin;
11274   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11275   /* Construct the coarse grid matrix */
11276   if (interpolate == restrct) {
11277     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11278   } else {
11279     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11280   }
11281 
11282   /* If the interpolation matrix is not of full rank, A will have zero rows.
11283      This can legitimately happen in the case of non-nested geometric multigrid.
11284      In that event, we set the rows of the matrix to the rows of the identity,
11285      ignoring the equations (as the RHS will also be zero). */
11286 
11287   PetscCall(MatFindZeroRows(*A, &zerorows));
11288 
11289   if (zerorows != NULL) { /* if there are any zero rows */
11290     PetscCall(MatCreateVecs(*A, &diag, NULL));
11291     PetscCall(MatGetDiagonal(*A, diag));
11292     PetscCall(VecISSet(diag, zerorows, 1.0));
11293     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11294     PetscCall(VecDestroy(&diag));
11295     PetscCall(ISDestroy(&zerorows));
11296   }
11297   PetscFunctionReturn(PETSC_SUCCESS);
11298 }
11299 
11300 /*@C
11301   MatSetOperation - Allows user to set a matrix operation for any matrix type
11302 
11303   Logically Collective
11304 
11305   Input Parameters:
11306 + mat - the matrix
11307 . op  - the name of the operation
11308 - f   - the function that provides the operation
11309 
11310   Level: developer
11311 
11312   Example Usage:
11313 .vb
11314   extern PetscErrorCode usermult(Mat, Vec, Vec);
11315 
11316   PetscCall(MatCreateXXX(comm, ..., &A));
11317   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11318 .ve
11319 
11320   Notes:
11321   See the file `include/petscmat.h` for a complete list of matrix
11322   operations, which all have the form MATOP_<OPERATION>, where
11323   <OPERATION> is the name (in all capital letters) of the
11324   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11325 
11326   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11327   sequence as the usual matrix interface routines, since they
11328   are intended to be accessed via the usual matrix interface
11329   routines, e.g.,
11330 .vb
11331   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11332 .ve
11333 
11334   In particular each function MUST return `PETSC_SUCCESS` on success and
11335   nonzero on failure.
11336 
11337   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11338 
11339 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11340 @*/
11341 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11342 {
11343   PetscFunctionBegin;
11344   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11345   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11346   (((void (**)(void))mat->ops)[op]) = f;
11347   PetscFunctionReturn(PETSC_SUCCESS);
11348 }
11349 
11350 /*@C
11351   MatGetOperation - Gets a matrix operation for any matrix type.
11352 
11353   Not Collective
11354 
11355   Input Parameters:
11356 + mat - the matrix
11357 - op  - the name of the operation
11358 
11359   Output Parameter:
11360 . f - the function that provides the operation
11361 
11362   Level: developer
11363 
11364   Example Usage:
11365 .vb
11366   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11367 
11368   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11369 .ve
11370 
11371   Notes:
11372   See the file include/petscmat.h for a complete list of matrix
11373   operations, which all have the form MATOP_<OPERATION>, where
11374   <OPERATION> is the name (in all capital letters) of the
11375   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11376 
11377   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11378 
11379 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11380 @*/
11381 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11382 {
11383   PetscFunctionBegin;
11384   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11385   *f = (((void (**)(void))mat->ops)[op]);
11386   PetscFunctionReturn(PETSC_SUCCESS);
11387 }
11388 
11389 /*@
11390   MatHasOperation - Determines whether the given matrix supports the particular operation.
11391 
11392   Not Collective
11393 
11394   Input Parameters:
11395 + mat - the matrix
11396 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11397 
11398   Output Parameter:
11399 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11400 
11401   Level: advanced
11402 
11403   Note:
11404   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11405 
11406 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11407 @*/
11408 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11409 {
11410   PetscFunctionBegin;
11411   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11412   PetscAssertPointer(has, 3);
11413   if (mat->ops->hasoperation) {
11414     PetscUseTypeMethod(mat, hasoperation, op, has);
11415   } else {
11416     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11417     else {
11418       *has = PETSC_FALSE;
11419       if (op == MATOP_CREATE_SUBMATRIX) {
11420         PetscMPIInt size;
11421 
11422         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11423         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11424       }
11425     }
11426   }
11427   PetscFunctionReturn(PETSC_SUCCESS);
11428 }
11429 
11430 /*@
11431   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11432 
11433   Collective
11434 
11435   Input Parameter:
11436 . mat - the matrix
11437 
11438   Output Parameter:
11439 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11440 
11441   Level: beginner
11442 
11443 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11444 @*/
11445 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11446 {
11447   PetscFunctionBegin;
11448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11449   PetscValidType(mat, 1);
11450   PetscAssertPointer(cong, 2);
11451   if (!mat->rmap || !mat->cmap) {
11452     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11453     PetscFunctionReturn(PETSC_SUCCESS);
11454   }
11455   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11456     PetscCall(PetscLayoutSetUp(mat->rmap));
11457     PetscCall(PetscLayoutSetUp(mat->cmap));
11458     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11459     if (*cong) mat->congruentlayouts = 1;
11460     else mat->congruentlayouts = 0;
11461   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11462   PetscFunctionReturn(PETSC_SUCCESS);
11463 }
11464 
11465 PetscErrorCode MatSetInf(Mat A)
11466 {
11467   PetscFunctionBegin;
11468   PetscUseTypeMethod(A, setinf);
11469   PetscFunctionReturn(PETSC_SUCCESS);
11470 }
11471 
11472 /*@
11473   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
11474   and possibly removes small values from the graph structure.
11475 
11476   Collective
11477 
11478   Input Parameters:
11479 + A       - the matrix
11480 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11481 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11482 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11483 . num_idx - size of 'index' array
11484 - index   - array of block indices to use for graph strength of connection weight
11485 
11486   Output Parameter:
11487 . graph - the resulting graph
11488 
11489   Level: advanced
11490 
11491 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11492 @*/
11493 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11494 {
11495   PetscFunctionBegin;
11496   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11497   PetscValidType(A, 1);
11498   PetscValidLogicalCollectiveBool(A, scale, 3);
11499   PetscAssertPointer(graph, 7);
11500   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11501   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11502   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11503   PetscFunctionReturn(PETSC_SUCCESS);
11504 }
11505 
11506 /*@
11507   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11508   meaning the same memory is used for the matrix, and no new memory is allocated.
11509 
11510   Collective
11511 
11512   Input Parameters:
11513 + A    - the matrix
11514 - 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
11515 
11516   Level: intermediate
11517 
11518   Developer Note:
11519   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11520   of the arrays in the data structure are unneeded.
11521 
11522 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11523 @*/
11524 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11525 {
11526   PetscFunctionBegin;
11527   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11528   PetscUseTypeMethod(A, eliminatezeros, keep);
11529   PetscFunctionReturn(PETSC_SUCCESS);
11530 }
11531