xref: /petsc/src/mat/interface/matrix.c (revision 687234bfd5affe98ea52f728ed48e32bff44d7bc)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_CreateGraph;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU;
43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
48 
49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
50 
51 /*@
52   MatSetRandom - Sets all components of a matrix to random numbers.
53 
54   Logically Collective
55 
56   Input Parameters:
57 + x    - the matrix
58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
59           it will create one internally.
60 
61   Example:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68   Level: intermediate
69 
70   Notes:
71   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
72 
73   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
74 
75   It generates an error if used on unassembled sparse matrices that have not been preallocated.
76 
77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108   MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type
109 
110   Logically Collective
111 
112   Input Parameter:
113 . A - A matrix in unassembled, hash table form
114 
115   Output Parameter:
116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()`
117 
118   Example:
119 .vb
120      PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B));
121      PetscCall(MatCopyHashToXAIJ(A, B));
122 .ve
123 
124   Level: advanced
125 
126   Notes:
127   If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled
128 
129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE`
130 @*/
131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
135   PetscUseTypeMethod(A, copyhashtoxaij, B);
136   PetscFunctionReturn(PETSC_SUCCESS);
137 }
138 
139 /*@
140   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
141 
142   Logically Collective
143 
144   Input Parameter:
145 . mat - the factored matrix
146 
147   Output Parameters:
148 + pivot - the pivot value computed
149 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
150          the share the matrix
151 
152   Level: advanced
153 
154   Notes:
155   This routine does not work for factorizations done with external packages.
156 
157   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
158 
159   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
160 
161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
163 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
164 @*/
165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
166 {
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
169   PetscAssertPointer(pivot, 2);
170   PetscAssertPointer(row, 3);
171   *pivot = mat->factorerror_zeropivot_value;
172   *row   = mat->factorerror_zeropivot_row;
173   PetscFunctionReturn(PETSC_SUCCESS);
174 }
175 
176 /*@
177   MatFactorGetError - gets the error code from a factorization
178 
179   Logically Collective
180 
181   Input Parameter:
182 . mat - the factored matrix
183 
184   Output Parameter:
185 . err - the error code
186 
187   Level: advanced
188 
189   Note:
190   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
191 
192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
193           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
194 @*/
195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
196 {
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
199   PetscAssertPointer(err, 2);
200   *err = mat->factorerrortype;
201   PetscFunctionReturn(PETSC_SUCCESS);
202 }
203 
204 /*@
205   MatFactorClearError - clears the error code in a factorization
206 
207   Logically Collective
208 
209   Input Parameter:
210 . mat - the factored matrix
211 
212   Level: developer
213 
214   Note:
215   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
216 
217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
218           `MatGetErrorCode()`, `MatFactorError`
219 @*/
220 PetscErrorCode MatFactorClearError(Mat mat)
221 {
222   PetscFunctionBegin;
223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
224   mat->factorerrortype             = MAT_FACTOR_NOERROR;
225   mat->factorerror_zeropivot_value = 0.0;
226   mat->factorerror_zeropivot_row   = 0;
227   PetscFunctionReturn(PETSC_SUCCESS);
228 }
229 
230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
231 {
232   Vec                r, l;
233   const PetscScalar *al;
234   PetscInt           i, nz, gnz, N, n, st;
235 
236   PetscFunctionBegin;
237   PetscCall(MatCreateVecs(mat, &r, &l));
238   if (!cols) { /* nonzero rows */
239     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
240     PetscCall(MatGetSize(mat, &N, NULL));
241     PetscCall(MatGetLocalSize(mat, &n, NULL));
242     PetscCall(VecSet(l, 0.0));
243     PetscCall(VecSetRandom(r, NULL));
244     PetscCall(MatMult(mat, r, l));
245     PetscCall(VecGetArrayRead(l, &al));
246   } else { /* nonzero columns */
247     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
248     PetscCall(MatGetSize(mat, NULL, &N));
249     PetscCall(MatGetLocalSize(mat, NULL, &n));
250     PetscCall(VecSet(r, 0.0));
251     PetscCall(VecSetRandom(l, NULL));
252     PetscCall(MatMultTranspose(mat, l, r));
253     PetscCall(VecGetArrayRead(r, &al));
254   }
255   if (tol <= 0.0) {
256     for (i = 0, nz = 0; i < n; i++)
257       if (al[i] != 0.0) nz++;
258   } else {
259     for (i = 0, nz = 0; i < n; i++)
260       if (PetscAbsScalar(al[i]) > tol) nz++;
261   }
262   PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
263   if (gnz != N) {
264     PetscInt *nzr;
265     PetscCall(PetscMalloc1(nz, &nzr));
266     if (nz) {
267       if (tol < 0) {
268         for (i = 0, nz = 0; i < n; i++)
269           if (al[i] != 0.0) nzr[nz++] = i + st;
270       } else {
271         for (i = 0, nz = 0; i < n; i++)
272           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
273       }
274     }
275     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
276   } else *nonzero = NULL;
277   if (!cols) { /* nonzero rows */
278     PetscCall(VecRestoreArrayRead(l, &al));
279   } else {
280     PetscCall(VecRestoreArrayRead(r, &al));
281   }
282   PetscCall(VecDestroy(&l));
283   PetscCall(VecDestroy(&r));
284   PetscFunctionReturn(PETSC_SUCCESS);
285 }
286 
287 /*@
288   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
289 
290   Input Parameter:
291 . mat - the matrix
292 
293   Output Parameter:
294 . keptrows - the rows that are not completely zero
295 
296   Level: intermediate
297 
298   Note:
299   `keptrows` is set to `NULL` if all rows are nonzero.
300 
301   Developer Note:
302   If `keptrows` is not `NULL`, it must be sorted.
303 
304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
305  @*/
306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
307 {
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
310   PetscValidType(mat, 1);
311   PetscAssertPointer(keptrows, 2);
312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
314   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
315   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
316   if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321   MatFindZeroRows - Locate all rows that are completely zero in the matrix
322 
323   Input Parameter:
324 . mat - the matrix
325 
326   Output Parameter:
327 . zerorows - the rows that are completely zero
328 
329   Level: intermediate
330 
331   Note:
332   `zerorows` is set to `NULL` if no rows are zero.
333 
334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
335  @*/
336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
337 {
338   IS       keptrows;
339   PetscInt m, n;
340 
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
343   PetscValidType(mat, 1);
344   PetscAssertPointer(zerorows, 2);
345   PetscCall(MatFindNonzeroRows(mat, &keptrows));
346   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
347      In keeping with this convention, we set zerorows to NULL if there are no zero
348      rows. */
349   if (keptrows == NULL) {
350     *zerorows = NULL;
351   } else {
352     PetscCall(MatGetOwnershipRange(mat, &m, &n));
353     PetscCall(ISComplement(keptrows, m, n, zerorows));
354     PetscCall(ISDestroy(&keptrows));
355   }
356   PetscFunctionReturn(PETSC_SUCCESS);
357 }
358 
359 /*@
360   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
361 
362   Not Collective
363 
364   Input Parameter:
365 . A - the matrix
366 
367   Output Parameter:
368 . a - the diagonal part (which is a SEQUENTIAL matrix)
369 
370   Level: advanced
371 
372   Notes:
373   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
374 
375   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
376 
377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
378 @*/
379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
380 {
381   PetscFunctionBegin;
382   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
383   PetscValidType(A, 1);
384   PetscAssertPointer(a, 2);
385   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
386   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
387   else {
388     PetscMPIInt size;
389 
390     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
391     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
392     *a = A;
393   }
394   PetscFunctionReturn(PETSC_SUCCESS);
395 }
396 
397 /*@
398   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
399 
400   Collective
401 
402   Input Parameter:
403 . mat - the matrix
404 
405   Output Parameter:
406 . trace - the sum of the diagonal entries
407 
408   Level: advanced
409 
410 .seealso: [](ch_matrices), `Mat`
411 @*/
412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
413 {
414   Vec diag;
415 
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
418   PetscAssertPointer(trace, 2);
419   PetscCall(MatCreateVecs(mat, &diag, NULL));
420   PetscCall(MatGetDiagonal(mat, diag));
421   PetscCall(VecSum(diag, trace));
422   PetscCall(VecDestroy(&diag));
423   PetscFunctionReturn(PETSC_SUCCESS);
424 }
425 
426 /*@
427   MatRealPart - Zeros out the imaginary part of the matrix
428 
429   Logically Collective
430 
431   Input Parameter:
432 . mat - the matrix
433 
434   Level: advanced
435 
436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
437 @*/
438 PetscErrorCode MatRealPart(Mat mat)
439 {
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
442   PetscValidType(mat, 1);
443   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
444   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
445   MatCheckPreallocated(mat, 1);
446   PetscUseTypeMethod(mat, realpart);
447   PetscFunctionReturn(PETSC_SUCCESS);
448 }
449 
450 /*@C
451   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
452 
453   Collective
454 
455   Input Parameter:
456 . mat - the matrix
457 
458   Output Parameters:
459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
460 - ghosts  - the global indices of the ghost points
461 
462   Level: advanced
463 
464   Note:
465   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
466 
467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
468 @*/
469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
470 {
471   PetscFunctionBegin;
472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
473   PetscValidType(mat, 1);
474   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
475   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
476   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
477   else {
478     if (nghosts) *nghosts = 0;
479     if (ghosts) *ghosts = NULL;
480   }
481   PetscFunctionReturn(PETSC_SUCCESS);
482 }
483 
484 /*@
485   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
486 
487   Logically Collective
488 
489   Input Parameter:
490 . mat - the matrix
491 
492   Level: advanced
493 
494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
495 @*/
496 PetscErrorCode MatImaginaryPart(Mat mat)
497 {
498   PetscFunctionBegin;
499   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
500   PetscValidType(mat, 1);
501   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
502   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
503   MatCheckPreallocated(mat, 1);
504   PetscUseTypeMethod(mat, imaginarypart);
505   PetscFunctionReturn(PETSC_SUCCESS);
506 }
507 
508 /*@
509   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
510 
511   Not Collective
512 
513   Input Parameter:
514 . mat - the matrix
515 
516   Output Parameters:
517 + missing - is any diagonal entry missing
518 - dd      - first diagonal entry that is missing (optional) on this process
519 
520   Level: advanced
521 
522   Note:
523   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
524 
525 .seealso: [](ch_matrices), `Mat`
526 @*/
527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
528 {
529   PetscFunctionBegin;
530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
531   PetscValidType(mat, 1);
532   PetscAssertPointer(missing, 2);
533   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
534   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
535   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
536   PetscFunctionReturn(PETSC_SUCCESS);
537 }
538 
539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
540 /*@C
541   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
542   for each row that you get to ensure that your application does
543   not bleed memory.
544 
545   Not Collective
546 
547   Input Parameters:
548 + mat - the matrix
549 - row - the row to get
550 
551   Output Parameters:
552 + ncols - if not `NULL`, the number of nonzeros in `row`
553 . cols  - if not `NULL`, the column numbers
554 - vals  - if not `NULL`, the numerical values
555 
556   Level: advanced
557 
558   Notes:
559   This routine is provided for people who need to have direct access
560   to the structure of a matrix.  We hope that we provide enough
561   high-level matrix routines that few users will need it.
562 
563   `MatGetRow()` always returns 0-based column indices, regardless of
564   whether the internal representation is 0-based (default) or 1-based.
565 
566   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
567   not wish to extract these quantities.
568 
569   The user can only examine the values extracted with `MatGetRow()`;
570   the values CANNOT be altered.  To change the matrix entries, one
571   must use `MatSetValues()`.
572 
573   You can only have one call to `MatGetRow()` outstanding for a particular
574   matrix at a time, per processor. `MatGetRow()` can only obtain rows
575   associated with the given processor, it cannot get rows from the
576   other processors; for that we suggest using `MatCreateSubMatrices()`, then
577   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
578   is in the global number of rows.
579 
580   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
581 
582   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
583 
584   Fortran Note:
585 .vb
586   PetscInt, pointer :: cols(:)
587   PetscScalar, pointer :: vals(:)
588 .ve
589 
590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
591 @*/
592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
593 {
594   PetscInt incols;
595 
596   PetscFunctionBegin;
597   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
598   PetscValidType(mat, 1);
599   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
600   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
601   MatCheckPreallocated(mat, 1);
602   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
603   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
604   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
605   if (ncols) *ncols = incols;
606   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
607   PetscFunctionReturn(PETSC_SUCCESS);
608 }
609 
610 /*@
611   MatConjugate - replaces the matrix values with their complex conjugates
612 
613   Logically Collective
614 
615   Input Parameter:
616 . mat - the matrix
617 
618   Level: advanced
619 
620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
621 @*/
622 PetscErrorCode MatConjugate(Mat mat)
623 {
624   PetscFunctionBegin;
625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
626   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
627   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
628     PetscUseTypeMethod(mat, conjugate);
629     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
630   }
631   PetscFunctionReturn(PETSC_SUCCESS);
632 }
633 
634 /*@C
635   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
636 
637   Not Collective
638 
639   Input Parameters:
640 + mat   - the matrix
641 . row   - the row to get
642 . ncols - the number of nonzeros
643 . cols  - the columns of the nonzeros
644 - vals  - if nonzero the column values
645 
646   Level: advanced
647 
648   Notes:
649   This routine should be called after you have finished examining the entries.
650 
651   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
652   us of the array after it has been restored. If you pass `NULL`, it will
653   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
654 
655   Fortran Note:
656 .vb
657   PetscInt, pointer :: cols(:)
658   PetscScalar, pointer :: vals(:)
659 .ve
660 
661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
662 @*/
663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
664 {
665   PetscFunctionBegin;
666   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
667   if (ncols) PetscAssertPointer(ncols, 3);
668   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
669   PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
670   if (ncols) *ncols = 0;
671   if (cols) *cols = NULL;
672   if (vals) *vals = NULL;
673   PetscFunctionReturn(PETSC_SUCCESS);
674 }
675 
676 /*@
677   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
678   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
679 
680   Not Collective
681 
682   Input Parameter:
683 . mat - the matrix
684 
685   Level: advanced
686 
687   Note:
688   The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
689 
690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   PetscTryTypeMethod(mat, getrowuppertriangular);
701   PetscFunctionReturn(PETSC_SUCCESS);
702 }
703 
704 /*@
705   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
706 
707   Not Collective
708 
709   Input Parameter:
710 . mat - the matrix
711 
712   Level: advanced
713 
714   Note:
715   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
716 
717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
718 @*/
719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
720 {
721   PetscFunctionBegin;
722   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
723   PetscValidType(mat, 1);
724   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
725   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
726   MatCheckPreallocated(mat, 1);
727   PetscTryTypeMethod(mat, restorerowuppertriangular);
728   PetscFunctionReturn(PETSC_SUCCESS);
729 }
730 
731 /*@
732   MatSetOptionsPrefix - Sets the prefix used for searching for all
733   `Mat` options in the database.
734 
735   Logically Collective
736 
737   Input Parameters:
738 + A      - the matrix
739 - prefix - the prefix to prepend to all option names
740 
741   Level: advanced
742 
743   Notes:
744   A hyphen (-) must NOT be given at the beginning of the prefix name.
745   The first character of all runtime options is AUTOMATICALLY the hyphen.
746 
747   This is NOT used for options for the factorization of the matrix. Normally the
748   prefix is automatically passed in from the PC calling the factorization. To set
749   it directly use  `MatSetOptionsPrefixFactor()`
750 
751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
752 @*/
753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
754 {
755   PetscFunctionBegin;
756   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
757   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
758   PetscFunctionReturn(PETSC_SUCCESS);
759 }
760 
761 /*@
762   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
763   for matrices created with `MatGetFactor()`
764 
765   Logically Collective
766 
767   Input Parameters:
768 + A      - the matrix
769 - prefix - the prefix to prepend to all option names for the factored matrix
770 
771   Level: developer
772 
773   Notes:
774   A hyphen (-) must NOT be given at the beginning of the prefix name.
775   The first character of all runtime options is AUTOMATICALLY the hyphen.
776 
777   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
778   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
779 
780 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
781 @*/
782 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
783 {
784   PetscFunctionBegin;
785   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
786   if (prefix) {
787     PetscAssertPointer(prefix, 2);
788     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
789     if (prefix != A->factorprefix) {
790       PetscCall(PetscFree(A->factorprefix));
791       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
792     }
793   } else PetscCall(PetscFree(A->factorprefix));
794   PetscFunctionReturn(PETSC_SUCCESS);
795 }
796 
797 /*@
798   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
799   for matrices created with `MatGetFactor()`
800 
801   Logically Collective
802 
803   Input Parameters:
804 + A      - the matrix
805 - prefix - the prefix to prepend to all option names for the factored matrix
806 
807   Level: developer
808 
809   Notes:
810   A hyphen (-) must NOT be given at the beginning of the prefix name.
811   The first character of all runtime options is AUTOMATICALLY the hyphen.
812 
813   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
814   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
815 
816 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
817           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
818           `MatSetOptionsPrefix()`
819 @*/
820 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
821 {
822   size_t len1, len2, new_len;
823 
824   PetscFunctionBegin;
825   PetscValidHeader(A, 1);
826   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
827   if (!A->factorprefix) {
828     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
829     PetscFunctionReturn(PETSC_SUCCESS);
830   }
831   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
832 
833   PetscCall(PetscStrlen(A->factorprefix, &len1));
834   PetscCall(PetscStrlen(prefix, &len2));
835   new_len = len1 + len2 + 1;
836   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
837   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
838   PetscFunctionReturn(PETSC_SUCCESS);
839 }
840 
841 /*@
842   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
843   matrix options in the database.
844 
845   Logically Collective
846 
847   Input Parameters:
848 + A      - the matrix
849 - prefix - the prefix to prepend to all option names
850 
851   Level: advanced
852 
853   Note:
854   A hyphen (-) must NOT be given at the beginning of the prefix name.
855   The first character of all runtime options is AUTOMATICALLY the hyphen.
856 
857 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
858 @*/
859 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
860 {
861   PetscFunctionBegin;
862   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
863   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
864   PetscFunctionReturn(PETSC_SUCCESS);
865 }
866 
867 /*@
868   MatGetOptionsPrefix - Gets the prefix used for searching for all
869   matrix options in the database.
870 
871   Not Collective
872 
873   Input Parameter:
874 . A - the matrix
875 
876   Output Parameter:
877 . prefix - pointer to the prefix string used
878 
879   Level: advanced
880 
881   Fortran Note:
882   The user should pass in a string `prefix` of
883   sufficient length to hold the prefix.
884 
885 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
886 @*/
887 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
888 {
889   PetscFunctionBegin;
890   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
891   PetscAssertPointer(prefix, 2);
892   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
893   PetscFunctionReturn(PETSC_SUCCESS);
894 }
895 
896 /*@
897   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
898 
899   Not Collective
900 
901   Input Parameter:
902 . A - the matrix
903 
904   Output Parameter:
905 . state - the object state
906 
907   Level: advanced
908 
909   Note:
910   Object state is an integer which gets increased every time
911   the object is changed. By saving and later querying the object state
912   one can determine whether information about the object is still current.
913 
914   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
915 
916 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
917 @*/
918 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
919 {
920   PetscFunctionBegin;
921   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
922   PetscAssertPointer(state, 2);
923   PetscCall(PetscObjectStateGet((PetscObject)A, state));
924   PetscFunctionReturn(PETSC_SUCCESS);
925 }
926 
927 /*@
928   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
929 
930   Collective
931 
932   Input Parameter:
933 . A - the matrix
934 
935   Level: beginner
936 
937   Notes:
938   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
939   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
940   makes all of the preallocation space available
941 
942   Current values in the matrix are lost in this call.
943 
944   Currently only supported for  `MATAIJ` matrices.
945 
946 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
947 @*/
948 PetscErrorCode MatResetPreallocation(Mat A)
949 {
950   PetscFunctionBegin;
951   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
952   PetscValidType(A, 1);
953   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()");
954   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
955   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
956   PetscFunctionReturn(PETSC_SUCCESS);
957 }
958 
959 /*@
960   MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
961 
962   Collective
963 
964   Input Parameter:
965 . A - the matrix
966 
967   Level: intermediate
968 
969   Notes:
970   The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
971 
972   Currently only supported for `MATAIJ` matrices.
973 
974 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
975 @*/
976 PetscErrorCode MatResetHash(Mat A)
977 {
978   PetscFunctionBegin;
979   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
980   PetscValidType(A, 1);
981   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()");
982   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
983   PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
984   /* These flags are used to determine whether certain setups occur */
985   A->was_assembled = PETSC_FALSE;
986   A->assembled     = PETSC_FALSE;
987   /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
988   PetscCall(PetscObjectStateIncrease((PetscObject)A));
989   PetscFunctionReturn(PETSC_SUCCESS);
990 }
991 
992 /*@
993   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
994 
995   Collective
996 
997   Input Parameter:
998 . A - the matrix
999 
1000   Level: advanced
1001 
1002   Notes:
1003   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
1004   setting values in the matrix.
1005 
1006   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
1007 
1008 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
1009 @*/
1010 PetscErrorCode MatSetUp(Mat A)
1011 {
1012   PetscFunctionBegin;
1013   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1014   if (!((PetscObject)A)->type_name) {
1015     PetscMPIInt size;
1016 
1017     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1018     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
1019   }
1020   if (!A->preallocated) PetscTryTypeMethod(A, setup);
1021   PetscCall(PetscLayoutSetUp(A->rmap));
1022   PetscCall(PetscLayoutSetUp(A->cmap));
1023   A->preallocated = PETSC_TRUE;
1024   PetscFunctionReturn(PETSC_SUCCESS);
1025 }
1026 
1027 #if defined(PETSC_HAVE_SAWS)
1028   #include <petscviewersaws.h>
1029 #endif
1030 
1031 /*
1032    If threadsafety is on extraneous matrices may be printed
1033 
1034    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1035 */
1036 #if !defined(PETSC_HAVE_THREADSAFETY)
1037 static PetscInt insidematview = 0;
1038 #endif
1039 
1040 /*@
1041   MatViewFromOptions - View properties of the matrix based on options set in the options database
1042 
1043   Collective
1044 
1045   Input Parameters:
1046 + A    - the matrix
1047 . obj  - optional additional object that provides the options prefix to use
1048 - name - command line option
1049 
1050   Options Database Key:
1051 . -mat_view [viewertype]:... - the viewer and its options
1052 
1053   Level: intermediate
1054 
1055   Note:
1056 .vb
1057     If no value is provided ascii:stdout is used
1058        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1059                                                   for example ascii::ascii_info prints just the information about the object not all details
1060                                                   unless :append is given filename opens in write mode, overwriting what was already there
1061        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1062        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1063        socket[:port]                             defaults to the standard output port
1064        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1065 .ve
1066 
1067 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1068 @*/
1069 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1070 {
1071   PetscFunctionBegin;
1072   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1073 #if !defined(PETSC_HAVE_THREADSAFETY)
1074   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1075 #endif
1076   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1077   PetscFunctionReturn(PETSC_SUCCESS);
1078 }
1079 
1080 /*@
1081   MatView - display information about a matrix in a variety ways
1082 
1083   Collective on viewer
1084 
1085   Input Parameters:
1086 + mat    - the matrix
1087 - viewer - visualization context
1088 
1089   Options Database Keys:
1090 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1091 . -mat_view ::ascii_info_detail    - Prints more detailed info
1092 . -mat_view                        - Prints matrix in ASCII format
1093 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1094 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1095 . -display <name>                  - Sets display name (default is host)
1096 . -draw_pause <sec>                - Sets number of seconds to pause after display
1097 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1098 . -viewer_socket_machine <machine> - -
1099 . -viewer_socket_port <port>       - -
1100 . -mat_view binary                 - save matrix to file in binary format
1101 - -viewer_binary_filename <name>   - -
1102 
1103   Level: beginner
1104 
1105   Notes:
1106   The available visualization contexts include
1107 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1108 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1109 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1110 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1111 
1112   The user can open alternative visualization contexts with
1113 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1114 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1115 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1116 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1117 
1118   The user can call `PetscViewerPushFormat()` to specify the output
1119   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1120   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1121 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1122 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1123 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1124 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1125 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1126 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1127 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1128 
1129   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1130   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1131 
1132   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1133 
1134   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1135   viewer is used.
1136 
1137   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1138   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1139 
1140   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1141   and then use the following mouse functions.
1142 .vb
1143   left mouse: zoom in
1144   middle mouse: zoom out
1145   right mouse: continue with the simulation
1146 .ve
1147 
1148 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1149           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1150 @*/
1151 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1152 {
1153   PetscInt          rows, cols, rbs, cbs;
1154   PetscBool         isascii, isstring, issaws;
1155   PetscViewerFormat format;
1156   PetscMPIInt       size;
1157 
1158   PetscFunctionBegin;
1159   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1160   PetscValidType(mat, 1);
1161   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1162   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1163 
1164   PetscCall(PetscViewerGetFormat(viewer, &format));
1165   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1166   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1167 
1168 #if !defined(PETSC_HAVE_THREADSAFETY)
1169   insidematview++;
1170 #endif
1171   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1172   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1173   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1174   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");
1175 
1176   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1177   if (isascii) {
1178     if (!mat->preallocated) {
1179       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1180 #if !defined(PETSC_HAVE_THREADSAFETY)
1181       insidematview--;
1182 #endif
1183       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1184       PetscFunctionReturn(PETSC_SUCCESS);
1185     }
1186     if (!mat->assembled) {
1187       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1188 #if !defined(PETSC_HAVE_THREADSAFETY)
1189       insidematview--;
1190 #endif
1191       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1192       PetscFunctionReturn(PETSC_SUCCESS);
1193     }
1194     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1195     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1196       MatNullSpace nullsp, transnullsp;
1197 
1198       PetscCall(PetscViewerASCIIPushTab(viewer));
1199       PetscCall(MatGetSize(mat, &rows, &cols));
1200       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1201       if (rbs != 1 || cbs != 1) {
1202         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" : ""));
1203         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1204       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1205       if (mat->factortype) {
1206         MatSolverType solver;
1207         PetscCall(MatFactorGetSolverType(mat, &solver));
1208         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1209       }
1210       if (mat->ops->getinfo) {
1211         MatInfo info;
1212         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1213         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1214         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1215       }
1216       PetscCall(MatGetNullSpace(mat, &nullsp));
1217       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1218       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1219       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1220       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1221       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1222       PetscCall(PetscViewerASCIIPushTab(viewer));
1223       PetscCall(MatProductView(mat, viewer));
1224       PetscCall(PetscViewerASCIIPopTab(viewer));
1225       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1226         IS tmp;
1227 
1228         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1229         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1230         PetscCall(PetscViewerASCIIPushTab(viewer));
1231         PetscCall(ISView(tmp, viewer));
1232         PetscCall(PetscViewerASCIIPopTab(viewer));
1233         PetscCall(ISDestroy(&tmp));
1234       }
1235     }
1236   } else if (issaws) {
1237 #if defined(PETSC_HAVE_SAWS)
1238     PetscMPIInt rank;
1239 
1240     PetscCall(PetscObjectName((PetscObject)mat));
1241     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1242     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1243 #endif
1244   } else if (isstring) {
1245     const char *type;
1246     PetscCall(MatGetType(mat, &type));
1247     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1248     PetscTryTypeMethod(mat, view, viewer);
1249   }
1250   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1251     PetscCall(PetscViewerASCIIPushTab(viewer));
1252     PetscUseTypeMethod(mat, viewnative, viewer);
1253     PetscCall(PetscViewerASCIIPopTab(viewer));
1254   } else if (mat->ops->view) {
1255     PetscCall(PetscViewerASCIIPushTab(viewer));
1256     PetscUseTypeMethod(mat, view, viewer);
1257     PetscCall(PetscViewerASCIIPopTab(viewer));
1258   }
1259   if (isascii) {
1260     PetscCall(PetscViewerGetFormat(viewer, &format));
1261     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1262   }
1263   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1264 #if !defined(PETSC_HAVE_THREADSAFETY)
1265   insidematview--;
1266 #endif
1267   PetscFunctionReturn(PETSC_SUCCESS);
1268 }
1269 
1270 #if defined(PETSC_USE_DEBUG)
1271   #include <../src/sys/totalview/tv_data_display.h>
1272 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1273 {
1274   TV_add_row("Local rows", "int", &mat->rmap->n);
1275   TV_add_row("Local columns", "int", &mat->cmap->n);
1276   TV_add_row("Global rows", "int", &mat->rmap->N);
1277   TV_add_row("Global columns", "int", &mat->cmap->N);
1278   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1279   return TV_format_OK;
1280 }
1281 #endif
1282 
1283 /*@
1284   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1285   with `MatView()`.  The matrix format is determined from the options database.
1286   Generates a parallel MPI matrix if the communicator has more than one
1287   processor.  The default matrix type is `MATAIJ`.
1288 
1289   Collective
1290 
1291   Input Parameters:
1292 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1293             or some related function before a call to `MatLoad()`
1294 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1295 
1296   Options Database Key:
1297 . -matload_block_size <bs> - set block size
1298 
1299   Level: beginner
1300 
1301   Notes:
1302   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1303   `Mat` before calling this routine if you wish to set it from the options database.
1304 
1305   `MatLoad()` automatically loads into the options database any options
1306   given in the file filename.info where filename is the name of the file
1307   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1308   file will be ignored if you use the -viewer_binary_skip_info option.
1309 
1310   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1311   sets the default matrix type AIJ and sets the local and global sizes.
1312   If type and/or size is already set, then the same are used.
1313 
1314   In parallel, each processor can load a subset of rows (or the
1315   entire matrix).  This routine is especially useful when a large
1316   matrix is stored on disk and only part of it is desired on each
1317   processor.  For example, a parallel solver may access only some of
1318   the rows from each processor.  The algorithm used here reads
1319   relatively small blocks of data rather than reading the entire
1320   matrix and then subsetting it.
1321 
1322   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1323   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1324   or the sequence like
1325 .vb
1326     `PetscViewer` v;
1327     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1328     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1329     `PetscViewerSetFromOptions`(v);
1330     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1331     `PetscViewerFileSetName`(v,"datafile");
1332 .ve
1333   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1334 $ -viewer_type {binary, hdf5}
1335 
1336   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1337   and src/mat/tutorials/ex10.c with the second approach.
1338 
1339   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1340   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1341   Multiple objects, both matrices and vectors, can be stored within the same file.
1342   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1343 
1344   Most users should not need to know the details of the binary storage
1345   format, since `MatLoad()` and `MatView()` completely hide these details.
1346   But for anyone who is interested, the standard binary matrix storage
1347   format is
1348 
1349 .vb
1350     PetscInt    MAT_FILE_CLASSID
1351     PetscInt    number of rows
1352     PetscInt    number of columns
1353     PetscInt    total number of nonzeros
1354     PetscInt    *number nonzeros in each row
1355     PetscInt    *column indices of all nonzeros (starting index is zero)
1356     PetscScalar *values of all nonzeros
1357 .ve
1358   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1359   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
1360   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1361 
1362   PETSc automatically does the byte swapping for
1363   machines that store the bytes reversed. Thus if you write your own binary
1364   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1365   and `PetscBinaryWrite()` to see how this may be done.
1366 
1367   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1368   Each processor's chunk is loaded independently by its owning MPI process.
1369   Multiple objects, both matrices and vectors, can be stored within the same file.
1370   They are looked up by their PetscObject name.
1371 
1372   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1373   by default the same structure and naming of the AIJ arrays and column count
1374   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1375 $    save example.mat A b -v7.3
1376   can be directly read by this routine (see Reference 1 for details).
1377 
1378   Depending on your MATLAB version, this format might be a default,
1379   otherwise you can set it as default in Preferences.
1380 
1381   Unless -nocompression flag is used to save the file in MATLAB,
1382   PETSc must be configured with ZLIB package.
1383 
1384   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1385 
1386   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1387 
1388   Corresponding `MatView()` is not yet implemented.
1389 
1390   The loaded matrix is actually a transpose of the original one in MATLAB,
1391   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1392   With this format, matrix is automatically transposed by PETSc,
1393   unless the matrix is marked as SPD or symmetric
1394   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1395 
1396   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1397 
1398 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1399  @*/
1400 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1401 {
1402   PetscBool flg;
1403 
1404   PetscFunctionBegin;
1405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1406   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1407 
1408   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1409 
1410   flg = PETSC_FALSE;
1411   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1412   if (flg) {
1413     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1414     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1415   }
1416   flg = PETSC_FALSE;
1417   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1418   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1419 
1420   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1421   PetscUseTypeMethod(mat, load, viewer);
1422   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1423   PetscFunctionReturn(PETSC_SUCCESS);
1424 }
1425 
1426 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1427 {
1428   Mat_Redundant *redund = *redundant;
1429 
1430   PetscFunctionBegin;
1431   if (redund) {
1432     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1433       PetscCall(ISDestroy(&redund->isrow));
1434       PetscCall(ISDestroy(&redund->iscol));
1435       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1436     } else {
1437       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1438       PetscCall(PetscFree(redund->sbuf_j));
1439       PetscCall(PetscFree(redund->sbuf_a));
1440       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1441         PetscCall(PetscFree(redund->rbuf_j[i]));
1442         PetscCall(PetscFree(redund->rbuf_a[i]));
1443       }
1444       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1445     }
1446 
1447     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1448     PetscCall(PetscFree(redund));
1449   }
1450   PetscFunctionReturn(PETSC_SUCCESS);
1451 }
1452 
1453 /*@
1454   MatDestroy - Frees space taken by a matrix.
1455 
1456   Collective
1457 
1458   Input Parameter:
1459 . A - the matrix
1460 
1461   Level: beginner
1462 
1463   Developer Note:
1464   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1465   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1466   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1467   if changes are needed here.
1468 
1469 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1470 @*/
1471 PetscErrorCode MatDestroy(Mat *A)
1472 {
1473   PetscFunctionBegin;
1474   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1475   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1476   if (--((PetscObject)*A)->refct > 0) {
1477     *A = NULL;
1478     PetscFunctionReturn(PETSC_SUCCESS);
1479   }
1480 
1481   /* if memory was published with SAWs then destroy it */
1482   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1483   PetscTryTypeMethod(*A, destroy);
1484 
1485   PetscCall(PetscFree((*A)->factorprefix));
1486   PetscCall(PetscFree((*A)->defaultvectype));
1487   PetscCall(PetscFree((*A)->defaultrandtype));
1488   PetscCall(PetscFree((*A)->bsizes));
1489   PetscCall(PetscFree((*A)->solvertype));
1490   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1491   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1492   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1493   PetscCall(MatProductClear(*A));
1494   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1495   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1496   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1497   PetscCall(MatDestroy(&(*A)->schur));
1498   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1499   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1500   PetscCall(PetscHeaderDestroy(A));
1501   PetscFunctionReturn(PETSC_SUCCESS);
1502 }
1503 
1504 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1505 /*@
1506   MatSetValues - Inserts or adds a block of values into a matrix.
1507   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1508   MUST be called after all calls to `MatSetValues()` have been completed.
1509 
1510   Not Collective
1511 
1512   Input Parameters:
1513 + mat  - the matrix
1514 . v    - a logically two-dimensional array of values
1515 . m    - the number of rows
1516 . idxm - the global indices of the rows
1517 . n    - the number of columns
1518 . idxn - the global indices of the columns
1519 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1520 
1521   Level: beginner
1522 
1523   Notes:
1524   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1525 
1526   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1527   options cannot be mixed without intervening calls to the assembly
1528   routines.
1529 
1530   `MatSetValues()` uses 0-based row and column numbers in Fortran
1531   as well as in C.
1532 
1533   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1534   simply ignored. This allows easily inserting element stiffness matrices
1535   with homogeneous Dirichlet boundary conditions that you don't want represented
1536   in the matrix.
1537 
1538   Efficiency Alert:
1539   The routine `MatSetValuesBlocked()` may offer much better efficiency
1540   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1541 
1542   Fortran Notes:
1543   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1544 .vb
1545   call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
1546 .ve
1547 
1548   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1549 
1550   Developer Note:
1551   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1552   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1553 
1554 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1555           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1556 @*/
1557 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1558 {
1559   PetscFunctionBeginHot;
1560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1561   PetscValidType(mat, 1);
1562   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1563   PetscAssertPointer(idxm, 3);
1564   PetscAssertPointer(idxn, 5);
1565   MatCheckPreallocated(mat, 1);
1566 
1567   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1568   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1569 
1570   if (PetscDefined(USE_DEBUG)) {
1571     PetscInt i, j;
1572 
1573     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1574     if (v) {
1575       for (i = 0; i < m; i++) {
1576         for (j = 0; j < n; j++) {
1577           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1578 #if defined(PETSC_USE_COMPLEX)
1579             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]);
1580 #else
1581             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]);
1582 #endif
1583         }
1584       }
1585     }
1586     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);
1587     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);
1588   }
1589 
1590   if (mat->assembled) {
1591     mat->was_assembled = PETSC_TRUE;
1592     mat->assembled     = PETSC_FALSE;
1593   }
1594   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1595   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1596   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1597   PetscFunctionReturn(PETSC_SUCCESS);
1598 }
1599 
1600 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1601 /*@
1602   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1603   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1604   MUST be called after all calls to `MatSetValues()` have been completed.
1605 
1606   Not Collective
1607 
1608   Input Parameters:
1609 + mat  - the matrix
1610 . v    - a logically two-dimensional array of values
1611 . ism  - the rows to provide
1612 . isn  - the columns to provide
1613 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1614 
1615   Level: beginner
1616 
1617   Notes:
1618   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1619 
1620   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1621   options cannot be mixed without intervening calls to the assembly
1622   routines.
1623 
1624   `MatSetValues()` uses 0-based row and column numbers in Fortran
1625   as well as in C.
1626 
1627   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1628   simply ignored. This allows easily inserting element stiffness matrices
1629   with homogeneous Dirichlet boundary conditions that you don't want represented
1630   in the matrix.
1631 
1632   Efficiency Alert:
1633   The routine `MatSetValuesBlocked()` may offer much better efficiency
1634   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1635 
1636   This is currently not optimized for any particular `ISType`
1637 
1638   Developer Note:
1639   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1640   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1641 
1642 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1643           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1644 @*/
1645 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1646 {
1647   PetscInt        m, n;
1648   const PetscInt *rows, *cols;
1649 
1650   PetscFunctionBeginHot;
1651   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1652   PetscCall(ISGetIndices(ism, &rows));
1653   PetscCall(ISGetIndices(isn, &cols));
1654   PetscCall(ISGetLocalSize(ism, &m));
1655   PetscCall(ISGetLocalSize(isn, &n));
1656   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1657   PetscCall(ISRestoreIndices(ism, &rows));
1658   PetscCall(ISRestoreIndices(isn, &cols));
1659   PetscFunctionReturn(PETSC_SUCCESS);
1660 }
1661 
1662 /*@
1663   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1664   values into a matrix
1665 
1666   Not Collective
1667 
1668   Input Parameters:
1669 + mat - the matrix
1670 . row - the (block) row to set
1671 - v   - a logically two-dimensional array of values
1672 
1673   Level: intermediate
1674 
1675   Notes:
1676   The values, `v`, are column-oriented (for the block version) and sorted
1677 
1678   All the nonzero values in `row` must be provided
1679 
1680   The matrix must have previously had its column indices set, likely by having been assembled.
1681 
1682   `row` must belong to this MPI process
1683 
1684 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1685           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1686 @*/
1687 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1688 {
1689   PetscInt globalrow;
1690 
1691   PetscFunctionBegin;
1692   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1693   PetscValidType(mat, 1);
1694   PetscAssertPointer(v, 3);
1695   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1696   PetscCall(MatSetValuesRow(mat, globalrow, v));
1697   PetscFunctionReturn(PETSC_SUCCESS);
1698 }
1699 
1700 /*@
1701   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1702   values into a matrix
1703 
1704   Not Collective
1705 
1706   Input Parameters:
1707 + mat - the matrix
1708 . row - the (block) row to set
1709 - 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
1710 
1711   Level: advanced
1712 
1713   Notes:
1714   The values, `v`, are column-oriented for the block version.
1715 
1716   All the nonzeros in `row` must be provided
1717 
1718   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1719 
1720   `row` must belong to this process
1721 
1722 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1723           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1724 @*/
1725 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1726 {
1727   PetscFunctionBeginHot;
1728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1729   PetscValidType(mat, 1);
1730   MatCheckPreallocated(mat, 1);
1731   PetscAssertPointer(v, 3);
1732   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1733   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1734   mat->insertmode = INSERT_VALUES;
1735 
1736   if (mat->assembled) {
1737     mat->was_assembled = PETSC_TRUE;
1738     mat->assembled     = PETSC_FALSE;
1739   }
1740   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1741   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1742   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1743   PetscFunctionReturn(PETSC_SUCCESS);
1744 }
1745 
1746 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1747 /*@
1748   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1749   Using structured grid indexing
1750 
1751   Not Collective
1752 
1753   Input Parameters:
1754 + mat  - the matrix
1755 . m    - number of rows being entered
1756 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1757 . n    - number of columns being entered
1758 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1759 . v    - a logically two-dimensional array of values
1760 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1761 
1762   Level: beginner
1763 
1764   Notes:
1765   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1766 
1767   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1768   options cannot be mixed without intervening calls to the assembly
1769   routines.
1770 
1771   The grid coordinates are across the entire grid, not just the local portion
1772 
1773   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1774   as well as in C.
1775 
1776   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1777 
1778   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1779   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1780 
1781   The columns and rows in the stencil passed in MUST be contained within the
1782   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1783   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1784   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1785   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1786 
1787   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1788   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1789   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1790   `DM_BOUNDARY_PERIODIC` boundary type.
1791 
1792   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
1793   a single value per point) you can skip filling those indices.
1794 
1795   Inspired by the structured grid interface to the HYPRE package
1796   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1797 
1798   Efficiency Alert:
1799   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1800   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1801 
1802 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1803           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1804 @*/
1805 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1806 {
1807   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1808   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1809   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1810 
1811   PetscFunctionBegin;
1812   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1814   PetscValidType(mat, 1);
1815   PetscAssertPointer(idxm, 3);
1816   PetscAssertPointer(idxn, 5);
1817 
1818   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1819     jdxm = buf;
1820     jdxn = buf + m;
1821   } else {
1822     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1823     jdxm = bufm;
1824     jdxn = bufn;
1825   }
1826   for (i = 0; i < m; i++) {
1827     for (j = 0; j < 3 - sdim; j++) dxm++;
1828     tmp = *dxm++ - starts[0];
1829     for (j = 0; j < dim - 1; j++) {
1830       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1831       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1832     }
1833     if (mat->stencil.noc) dxm++;
1834     jdxm[i] = tmp;
1835   }
1836   for (i = 0; i < n; i++) {
1837     for (j = 0; j < 3 - sdim; j++) dxn++;
1838     tmp = *dxn++ - starts[0];
1839     for (j = 0; j < dim - 1; j++) {
1840       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1841       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1842     }
1843     if (mat->stencil.noc) dxn++;
1844     jdxn[i] = tmp;
1845   }
1846   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1847   PetscCall(PetscFree2(bufm, bufn));
1848   PetscFunctionReturn(PETSC_SUCCESS);
1849 }
1850 
1851 /*@
1852   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1853   Using structured grid indexing
1854 
1855   Not Collective
1856 
1857   Input Parameters:
1858 + mat  - the matrix
1859 . m    - number of rows being entered
1860 . idxm - grid coordinates for matrix rows being entered
1861 . n    - number of columns being entered
1862 . idxn - grid coordinates for matrix columns being entered
1863 . v    - a logically two-dimensional array of values
1864 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1865 
1866   Level: beginner
1867 
1868   Notes:
1869   By default the values, `v`, are row-oriented and unsorted.
1870   See `MatSetOption()` for other options.
1871 
1872   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1873   options cannot be mixed without intervening calls to the assembly
1874   routines.
1875 
1876   The grid coordinates are across the entire grid, not just the local portion
1877 
1878   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1879   as well as in C.
1880 
1881   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1882 
1883   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1884   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1885 
1886   The columns and rows in the stencil passed in MUST be contained within the
1887   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1888   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1889   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1890   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1891 
1892   Negative indices may be passed in idxm and idxn, these rows and columns are
1893   simply ignored. This allows easily inserting element stiffness matrices
1894   with homogeneous Dirichlet boundary conditions that you don't want represented
1895   in the matrix.
1896 
1897   Inspired by the structured grid interface to the HYPRE package
1898   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1899 
1900   Fortran Note:
1901   `idxm` and `idxn` should be declared as
1902 $     MatStencil idxm(4,m),idxn(4,n)
1903   and the values inserted using
1904 .vb
1905     idxm(MatStencil_i,1) = i
1906     idxm(MatStencil_j,1) = j
1907     idxm(MatStencil_k,1) = k
1908    etc
1909 .ve
1910 
1911 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1912           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1913           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1914 @*/
1915 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1916 {
1917   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1918   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1919   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1920 
1921   PetscFunctionBegin;
1922   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1923   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1924   PetscValidType(mat, 1);
1925   PetscAssertPointer(idxm, 3);
1926   PetscAssertPointer(idxn, 5);
1927   PetscAssertPointer(v, 6);
1928 
1929   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1930     jdxm = buf;
1931     jdxn = buf + m;
1932   } else {
1933     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1934     jdxm = bufm;
1935     jdxn = bufn;
1936   }
1937   for (i = 0; i < m; i++) {
1938     for (j = 0; j < 3 - sdim; j++) dxm++;
1939     tmp = *dxm++ - starts[0];
1940     for (j = 0; j < sdim - 1; j++) {
1941       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1942       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1943     }
1944     dxm++;
1945     jdxm[i] = tmp;
1946   }
1947   for (i = 0; i < n; i++) {
1948     for (j = 0; j < 3 - sdim; j++) dxn++;
1949     tmp = *dxn++ - starts[0];
1950     for (j = 0; j < sdim - 1; j++) {
1951       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1952       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1953     }
1954     dxn++;
1955     jdxn[i] = tmp;
1956   }
1957   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1958   PetscCall(PetscFree2(bufm, bufn));
1959   PetscFunctionReturn(PETSC_SUCCESS);
1960 }
1961 
1962 /*@
1963   MatSetStencil - Sets the grid information for setting values into a matrix via
1964   `MatSetValuesStencil()`
1965 
1966   Not Collective
1967 
1968   Input Parameters:
1969 + mat    - the matrix
1970 . dim    - dimension of the grid 1, 2, or 3
1971 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1972 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1973 - dof    - number of degrees of freedom per node
1974 
1975   Level: beginner
1976 
1977   Notes:
1978   Inspired by the structured grid interface to the HYPRE package
1979   (www.llnl.gov/CASC/hyper)
1980 
1981   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1982   user.
1983 
1984 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1985           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1986 @*/
1987 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1988 {
1989   PetscFunctionBegin;
1990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1991   PetscAssertPointer(dims, 3);
1992   PetscAssertPointer(starts, 4);
1993 
1994   mat->stencil.dim = dim + (dof > 1);
1995   for (PetscInt i = 0; i < dim; i++) {
1996     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1997     mat->stencil.starts[i] = starts[dim - i - 1];
1998   }
1999   mat->stencil.dims[dim]   = dof;
2000   mat->stencil.starts[dim] = 0;
2001   mat->stencil.noc         = (PetscBool)(dof == 1);
2002   PetscFunctionReturn(PETSC_SUCCESS);
2003 }
2004 
2005 /*@
2006   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
2007 
2008   Not Collective
2009 
2010   Input Parameters:
2011 + mat  - the matrix
2012 . v    - a logically two-dimensional array of values
2013 . m    - the number of block rows
2014 . idxm - the global block indices
2015 . n    - the number of block columns
2016 . idxn - the global block indices
2017 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
2018 
2019   Level: intermediate
2020 
2021   Notes:
2022   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
2023   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
2024 
2025   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
2026   NOT the total number of rows/columns; for example, if the block size is 2 and
2027   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
2028   The values in `idxm` would be 1 2; that is the first index for each block divided by
2029   the block size.
2030 
2031   You must call `MatSetBlockSize()` when constructing this matrix (before
2032   preallocating it).
2033 
2034   By default the values, `v`, are row-oriented, so the layout of
2035   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
2036 
2037   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
2038   options cannot be mixed without intervening calls to the assembly
2039   routines.
2040 
2041   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2042   as well as in C.
2043 
2044   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2045   simply ignored. This allows easily inserting element stiffness matrices
2046   with homogeneous Dirichlet boundary conditions that you don't want represented
2047   in the matrix.
2048 
2049   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2050   internal searching must be done to determine where to place the
2051   data in the matrix storage space.  By instead inserting blocks of
2052   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2053   reduced.
2054 
2055   Example:
2056 .vb
2057    Suppose m=n=2 and block size(bs) = 2 The array is
2058 
2059    1  2  | 3  4
2060    5  6  | 7  8
2061    - - - | - - -
2062    9  10 | 11 12
2063    13 14 | 15 16
2064 
2065    v[] should be passed in like
2066    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2067 
2068   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2069    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2070 .ve
2071 
2072   Fortran Notes:
2073   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2074 .vb
2075   call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
2076 .ve
2077 
2078   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2079 
2080 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2081 @*/
2082 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2083 {
2084   PetscFunctionBeginHot;
2085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2086   PetscValidType(mat, 1);
2087   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2088   PetscAssertPointer(idxm, 3);
2089   PetscAssertPointer(idxn, 5);
2090   MatCheckPreallocated(mat, 1);
2091   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2092   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2093   if (PetscDefined(USE_DEBUG)) {
2094     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2095     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2096   }
2097   if (PetscDefined(USE_DEBUG)) {
2098     PetscInt rbs, cbs, M, N, i;
2099     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2100     PetscCall(MatGetSize(mat, &M, &N));
2101     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);
2102     for (i = 0; i < n; i++)
2103       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);
2104   }
2105   if (mat->assembled) {
2106     mat->was_assembled = PETSC_TRUE;
2107     mat->assembled     = PETSC_FALSE;
2108   }
2109   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2110   if (mat->ops->setvaluesblocked) {
2111     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2112   } else {
2113     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2114     PetscInt i, j, bs, cbs;
2115 
2116     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2117     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2118       iidxm = buf;
2119       iidxn = buf + m * bs;
2120     } else {
2121       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2122       iidxm = bufr;
2123       iidxn = bufc;
2124     }
2125     for (i = 0; i < m; i++) {
2126       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2127     }
2128     if (m != n || bs != cbs || idxm != idxn) {
2129       for (i = 0; i < n; i++) {
2130         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2131       }
2132     } else iidxn = iidxm;
2133     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2134     PetscCall(PetscFree2(bufr, bufc));
2135   }
2136   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2137   PetscFunctionReturn(PETSC_SUCCESS);
2138 }
2139 
2140 /*@
2141   MatGetValues - Gets a block of local values from a matrix.
2142 
2143   Not Collective; can only return values that are owned by the give process
2144 
2145   Input Parameters:
2146 + mat  - the matrix
2147 . v    - a logically two-dimensional array for storing the values
2148 . m    - the number of rows
2149 . idxm - the  global indices of the rows
2150 . n    - the number of columns
2151 - idxn - the global indices of the columns
2152 
2153   Level: advanced
2154 
2155   Notes:
2156   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2157   The values, `v`, are then returned in a row-oriented format,
2158   analogous to that used by default in `MatSetValues()`.
2159 
2160   `MatGetValues()` uses 0-based row and column numbers in
2161   Fortran as well as in C.
2162 
2163   `MatGetValues()` requires that the matrix has been assembled
2164   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2165   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2166   without intermediate matrix assembly.
2167 
2168   Negative row or column indices will be ignored and those locations in `v` will be
2169   left unchanged.
2170 
2171   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2172   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2173   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2174 
2175 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2176 @*/
2177 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2178 {
2179   PetscFunctionBegin;
2180   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2181   PetscValidType(mat, 1);
2182   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2183   PetscAssertPointer(idxm, 3);
2184   PetscAssertPointer(idxn, 5);
2185   PetscAssertPointer(v, 6);
2186   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2187   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2188   MatCheckPreallocated(mat, 1);
2189 
2190   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2191   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2192   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2193   PetscFunctionReturn(PETSC_SUCCESS);
2194 }
2195 
2196 /*@
2197   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2198   defined previously by `MatSetLocalToGlobalMapping()`
2199 
2200   Not Collective
2201 
2202   Input Parameters:
2203 + mat  - the matrix
2204 . nrow - number of rows
2205 . irow - the row local indices
2206 . ncol - number of columns
2207 - icol - the column local indices
2208 
2209   Output Parameter:
2210 . y - a logically two-dimensional array of values
2211 
2212   Level: advanced
2213 
2214   Notes:
2215   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2216 
2217   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,
2218   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2219   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2220   with `MatSetLocalToGlobalMapping()`.
2221 
2222   Developer Note:
2223   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2224   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2225 
2226 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2227           `MatSetValuesLocal()`, `MatGetValues()`
2228 @*/
2229 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2230 {
2231   PetscFunctionBeginHot;
2232   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2233   PetscValidType(mat, 1);
2234   MatCheckPreallocated(mat, 1);
2235   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2236   PetscAssertPointer(irow, 3);
2237   PetscAssertPointer(icol, 5);
2238   if (PetscDefined(USE_DEBUG)) {
2239     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2240     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2241   }
2242   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2243   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2244   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2245   else {
2246     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2247     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2248       irowm = buf;
2249       icolm = buf + nrow;
2250     } else {
2251       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2252       irowm = bufr;
2253       icolm = bufc;
2254     }
2255     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2256     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2257     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2258     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2259     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2260     PetscCall(PetscFree2(bufr, bufc));
2261   }
2262   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2263   PetscFunctionReturn(PETSC_SUCCESS);
2264 }
2265 
2266 /*@
2267   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2268   the same size. Currently, this can only be called once and creates the given matrix.
2269 
2270   Not Collective
2271 
2272   Input Parameters:
2273 + mat  - the matrix
2274 . nb   - the number of blocks
2275 . bs   - the number of rows (and columns) in each block
2276 . rows - a concatenation of the rows for each block
2277 - v    - a concatenation of logically two-dimensional arrays of values
2278 
2279   Level: advanced
2280 
2281   Notes:
2282   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2283 
2284   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2285 
2286 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2287           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2288 @*/
2289 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2290 {
2291   PetscFunctionBegin;
2292   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2293   PetscValidType(mat, 1);
2294   PetscAssertPointer(rows, 4);
2295   PetscAssertPointer(v, 5);
2296   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2297 
2298   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2299   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2300   else {
2301     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2302   }
2303   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2304   PetscFunctionReturn(PETSC_SUCCESS);
2305 }
2306 
2307 /*@
2308   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2309   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2310   using a local (per-processor) numbering.
2311 
2312   Not Collective
2313 
2314   Input Parameters:
2315 + x        - the matrix
2316 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2317 - cmapping - column mapping
2318 
2319   Level: intermediate
2320 
2321   Note:
2322   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2323 
2324 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2325 @*/
2326 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2327 {
2328   PetscFunctionBegin;
2329   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2330   PetscValidType(x, 1);
2331   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2332   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2333   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2334   else {
2335     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2336     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2337   }
2338   PetscFunctionReturn(PETSC_SUCCESS);
2339 }
2340 
2341 /*@
2342   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2343 
2344   Not Collective
2345 
2346   Input Parameter:
2347 . A - the matrix
2348 
2349   Output Parameters:
2350 + rmapping - row mapping
2351 - cmapping - column mapping
2352 
2353   Level: advanced
2354 
2355 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2356 @*/
2357 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2358 {
2359   PetscFunctionBegin;
2360   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2361   PetscValidType(A, 1);
2362   if (rmapping) {
2363     PetscAssertPointer(rmapping, 2);
2364     *rmapping = A->rmap->mapping;
2365   }
2366   if (cmapping) {
2367     PetscAssertPointer(cmapping, 3);
2368     *cmapping = A->cmap->mapping;
2369   }
2370   PetscFunctionReturn(PETSC_SUCCESS);
2371 }
2372 
2373 /*@
2374   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2375 
2376   Logically Collective
2377 
2378   Input Parameters:
2379 + A    - the matrix
2380 . rmap - row layout
2381 - cmap - column layout
2382 
2383   Level: advanced
2384 
2385   Note:
2386   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2387 
2388 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2389 @*/
2390 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2391 {
2392   PetscFunctionBegin;
2393   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2394   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2395   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2396   PetscFunctionReturn(PETSC_SUCCESS);
2397 }
2398 
2399 /*@
2400   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2401 
2402   Not Collective
2403 
2404   Input Parameter:
2405 . A - the matrix
2406 
2407   Output Parameters:
2408 + rmap - row layout
2409 - cmap - column layout
2410 
2411   Level: advanced
2412 
2413 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2414 @*/
2415 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2416 {
2417   PetscFunctionBegin;
2418   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2419   PetscValidType(A, 1);
2420   if (rmap) {
2421     PetscAssertPointer(rmap, 2);
2422     *rmap = A->rmap;
2423   }
2424   if (cmap) {
2425     PetscAssertPointer(cmap, 3);
2426     *cmap = A->cmap;
2427   }
2428   PetscFunctionReturn(PETSC_SUCCESS);
2429 }
2430 
2431 /*@
2432   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2433   using a local numbering of the rows and columns.
2434 
2435   Not Collective
2436 
2437   Input Parameters:
2438 + mat  - the matrix
2439 . nrow - number of rows
2440 . irow - the row local indices
2441 . ncol - number of columns
2442 . icol - the column local indices
2443 . y    - a logically two-dimensional array of values
2444 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2445 
2446   Level: intermediate
2447 
2448   Notes:
2449   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2450 
2451   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2452   options cannot be mixed without intervening calls to the assembly
2453   routines.
2454 
2455   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2456   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2457 
2458   Fortran Notes:
2459   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2460 .vb
2461   call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2462 .ve
2463 
2464   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2465 
2466   Developer Note:
2467   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2468   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2469 
2470 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2471           `MatGetValuesLocal()`
2472 @*/
2473 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2474 {
2475   PetscFunctionBeginHot;
2476   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2477   PetscValidType(mat, 1);
2478   MatCheckPreallocated(mat, 1);
2479   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2480   PetscAssertPointer(irow, 3);
2481   PetscAssertPointer(icol, 5);
2482   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2483   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2484   if (PetscDefined(USE_DEBUG)) {
2485     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2486     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2487   }
2488 
2489   if (mat->assembled) {
2490     mat->was_assembled = PETSC_TRUE;
2491     mat->assembled     = PETSC_FALSE;
2492   }
2493   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2494   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2495   else {
2496     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2497     const PetscInt *irowm, *icolm;
2498 
2499     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2500       bufr  = buf;
2501       bufc  = buf + nrow;
2502       irowm = bufr;
2503       icolm = bufc;
2504     } else {
2505       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2506       irowm = bufr;
2507       icolm = bufc;
2508     }
2509     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2510     else irowm = irow;
2511     if (mat->cmap->mapping) {
2512       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2513         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2514       } else icolm = irowm;
2515     } else icolm = icol;
2516     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2517     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2518   }
2519   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2520   PetscFunctionReturn(PETSC_SUCCESS);
2521 }
2522 
2523 /*@
2524   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2525   using a local ordering of the nodes a block at a time.
2526 
2527   Not Collective
2528 
2529   Input Parameters:
2530 + mat  - the matrix
2531 . nrow - number of rows
2532 . irow - the row local indices
2533 . ncol - number of columns
2534 . icol - the column local indices
2535 . y    - a logically two-dimensional array of values
2536 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2537 
2538   Level: intermediate
2539 
2540   Notes:
2541   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2542   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2543 
2544   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2545   options cannot be mixed without intervening calls to the assembly
2546   routines.
2547 
2548   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2549   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2550 
2551   Fortran Notes:
2552   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2553 .vb
2554   call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2555 .ve
2556 
2557   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2558 
2559   Developer Note:
2560   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2561   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2562 
2563 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2564           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2565 @*/
2566 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2567 {
2568   PetscFunctionBeginHot;
2569   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2570   PetscValidType(mat, 1);
2571   MatCheckPreallocated(mat, 1);
2572   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2573   PetscAssertPointer(irow, 3);
2574   PetscAssertPointer(icol, 5);
2575   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2576   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2577   if (PetscDefined(USE_DEBUG)) {
2578     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2579     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);
2580   }
2581 
2582   if (mat->assembled) {
2583     mat->was_assembled = PETSC_TRUE;
2584     mat->assembled     = PETSC_FALSE;
2585   }
2586   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2587     PetscInt irbs, rbs;
2588     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2589     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2590     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2591   }
2592   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2593     PetscInt icbs, cbs;
2594     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2595     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2596     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2597   }
2598   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2599   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2600   else {
2601     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2602     const PetscInt *irowm, *icolm;
2603 
2604     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2605       bufr  = buf;
2606       bufc  = buf + nrow;
2607       irowm = bufr;
2608       icolm = bufc;
2609     } else {
2610       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2611       irowm = bufr;
2612       icolm = bufc;
2613     }
2614     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2615     else irowm = irow;
2616     if (mat->cmap->mapping) {
2617       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2618         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2619       } else icolm = irowm;
2620     } else icolm = icol;
2621     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2622     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2623   }
2624   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2625   PetscFunctionReturn(PETSC_SUCCESS);
2626 }
2627 
2628 /*@
2629   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2630 
2631   Collective
2632 
2633   Input Parameters:
2634 + mat - the matrix
2635 - x   - the vector to be multiplied
2636 
2637   Output Parameter:
2638 . y - the result
2639 
2640   Level: developer
2641 
2642   Note:
2643   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2644   call `MatMultDiagonalBlock`(A,y,y).
2645 
2646 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2647 @*/
2648 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2649 {
2650   PetscFunctionBegin;
2651   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2652   PetscValidType(mat, 1);
2653   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2654   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2655 
2656   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2657   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2658   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2659   MatCheckPreallocated(mat, 1);
2660 
2661   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2662   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2663   PetscFunctionReturn(PETSC_SUCCESS);
2664 }
2665 
2666 /*@
2667   MatMult - Computes the matrix-vector product, $y = Ax$.
2668 
2669   Neighbor-wise Collective
2670 
2671   Input Parameters:
2672 + mat - the matrix
2673 - x   - the vector to be multiplied
2674 
2675   Output Parameter:
2676 . y - the result
2677 
2678   Level: beginner
2679 
2680   Note:
2681   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2682   call `MatMult`(A,y,y).
2683 
2684 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2685 @*/
2686 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2687 {
2688   PetscFunctionBegin;
2689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2690   PetscValidType(mat, 1);
2691   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2692   VecCheckAssembled(x);
2693   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2694   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2695   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2696   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2697   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);
2698   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);
2699   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);
2700   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);
2701   PetscCall(VecSetErrorIfLocked(y, 3));
2702   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2703   MatCheckPreallocated(mat, 1);
2704 
2705   PetscCall(VecLockReadPush(x));
2706   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2707   PetscUseTypeMethod(mat, mult, x, y);
2708   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2709   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2710   PetscCall(VecLockReadPop(x));
2711   PetscFunctionReturn(PETSC_SUCCESS);
2712 }
2713 
2714 /*@
2715   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2716 
2717   Neighbor-wise Collective
2718 
2719   Input Parameters:
2720 + mat - the matrix
2721 - x   - the vector to be multiplied
2722 
2723   Output Parameter:
2724 . y - the result
2725 
2726   Level: beginner
2727 
2728   Notes:
2729   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2730   call `MatMultTranspose`(A,y,y).
2731 
2732   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2733   use `MatMultHermitianTranspose()`
2734 
2735 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2736 @*/
2737 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2738 {
2739   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2740 
2741   PetscFunctionBegin;
2742   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2743   PetscValidType(mat, 1);
2744   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2745   VecCheckAssembled(x);
2746   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2747 
2748   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2749   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2750   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2751   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);
2752   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);
2753   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);
2754   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);
2755   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2756   MatCheckPreallocated(mat, 1);
2757 
2758   if (!mat->ops->multtranspose) {
2759     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2760     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);
2761   } else op = mat->ops->multtranspose;
2762   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2763   PetscCall(VecLockReadPush(x));
2764   PetscCall((*op)(mat, x, y));
2765   PetscCall(VecLockReadPop(x));
2766   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2767   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2768   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2769   PetscFunctionReturn(PETSC_SUCCESS);
2770 }
2771 
2772 /*@
2773   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2774 
2775   Neighbor-wise Collective
2776 
2777   Input Parameters:
2778 + mat - the matrix
2779 - x   - the vector to be multiplied
2780 
2781   Output Parameter:
2782 . y - the result
2783 
2784   Level: beginner
2785 
2786   Notes:
2787   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2788   call `MatMultHermitianTranspose`(A,y,y).
2789 
2790   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2791 
2792   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2793 
2794 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2795 @*/
2796 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2797 {
2798   PetscFunctionBegin;
2799   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2800   PetscValidType(mat, 1);
2801   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2802   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2803 
2804   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2805   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2806   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2807   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);
2808   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);
2809   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);
2810   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);
2811   MatCheckPreallocated(mat, 1);
2812 
2813   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2814 #if defined(PETSC_USE_COMPLEX)
2815   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2816     PetscCall(VecLockReadPush(x));
2817     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2818     else PetscUseTypeMethod(mat, mult, x, y);
2819     PetscCall(VecLockReadPop(x));
2820   } else {
2821     Vec w;
2822     PetscCall(VecDuplicate(x, &w));
2823     PetscCall(VecCopy(x, w));
2824     PetscCall(VecConjugate(w));
2825     PetscCall(MatMultTranspose(mat, w, y));
2826     PetscCall(VecDestroy(&w));
2827     PetscCall(VecConjugate(y));
2828   }
2829   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2830 #else
2831   PetscCall(MatMultTranspose(mat, x, y));
2832 #endif
2833   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2834   PetscFunctionReturn(PETSC_SUCCESS);
2835 }
2836 
2837 /*@
2838   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2839 
2840   Neighbor-wise Collective
2841 
2842   Input Parameters:
2843 + mat - the matrix
2844 . v1  - the vector to be multiplied by `mat`
2845 - v2  - the vector to be added to the result
2846 
2847   Output Parameter:
2848 . v3 - the result
2849 
2850   Level: beginner
2851 
2852   Note:
2853   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2854   call `MatMultAdd`(A,v1,v2,v1).
2855 
2856 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2857 @*/
2858 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2859 {
2860   PetscFunctionBegin;
2861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2862   PetscValidType(mat, 1);
2863   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2864   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2865   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2866 
2867   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2868   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2869   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);
2870   /* 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);
2871      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); */
2872   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);
2873   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);
2874   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2875   MatCheckPreallocated(mat, 1);
2876 
2877   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2878   PetscCall(VecLockReadPush(v1));
2879   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2880   PetscCall(VecLockReadPop(v1));
2881   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2882   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2883   PetscFunctionReturn(PETSC_SUCCESS);
2884 }
2885 
2886 /*@
2887   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2888 
2889   Neighbor-wise Collective
2890 
2891   Input Parameters:
2892 + mat - the matrix
2893 . v1  - the vector to be multiplied by the transpose of the matrix
2894 - v2  - the vector to be added to the result
2895 
2896   Output Parameter:
2897 . v3 - the result
2898 
2899   Level: beginner
2900 
2901   Note:
2902   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2903   call `MatMultTransposeAdd`(A,v1,v2,v1).
2904 
2905 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2906 @*/
2907 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2908 {
2909   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2910 
2911   PetscFunctionBegin;
2912   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2913   PetscValidType(mat, 1);
2914   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2915   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2916   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2917 
2918   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2919   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2920   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);
2921   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);
2922   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);
2923   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2924   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2925   MatCheckPreallocated(mat, 1);
2926 
2927   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2928   PetscCall(VecLockReadPush(v1));
2929   PetscCall((*op)(mat, v1, v2, v3));
2930   PetscCall(VecLockReadPop(v1));
2931   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2932   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2933   PetscFunctionReturn(PETSC_SUCCESS);
2934 }
2935 
2936 /*@
2937   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2938 
2939   Neighbor-wise Collective
2940 
2941   Input Parameters:
2942 + mat - the matrix
2943 . v1  - the vector to be multiplied by the Hermitian transpose
2944 - v2  - the vector to be added to the result
2945 
2946   Output Parameter:
2947 . v3 - the result
2948 
2949   Level: beginner
2950 
2951   Note:
2952   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2953   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2954 
2955 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2956 @*/
2957 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2958 {
2959   PetscFunctionBegin;
2960   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2961   PetscValidType(mat, 1);
2962   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2963   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2964   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2965 
2966   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2967   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2968   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2969   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);
2970   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);
2971   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);
2972   MatCheckPreallocated(mat, 1);
2973 
2974   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2975   PetscCall(VecLockReadPush(v1));
2976   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2977   else {
2978     Vec w, z;
2979     PetscCall(VecDuplicate(v1, &w));
2980     PetscCall(VecCopy(v1, w));
2981     PetscCall(VecConjugate(w));
2982     PetscCall(VecDuplicate(v3, &z));
2983     PetscCall(MatMultTranspose(mat, w, z));
2984     PetscCall(VecDestroy(&w));
2985     PetscCall(VecConjugate(z));
2986     if (v2 != v3) {
2987       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2988     } else {
2989       PetscCall(VecAXPY(v3, 1.0, z));
2990     }
2991     PetscCall(VecDestroy(&z));
2992   }
2993   PetscCall(VecLockReadPop(v1));
2994   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2995   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2996   PetscFunctionReturn(PETSC_SUCCESS);
2997 }
2998 
2999 /*@
3000   MatGetFactorType - gets the type of factorization a matrix is
3001 
3002   Not Collective
3003 
3004   Input Parameter:
3005 . mat - the matrix
3006 
3007   Output Parameter:
3008 . 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`
3009 
3010   Level: intermediate
3011 
3012 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3013           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3014 @*/
3015 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
3016 {
3017   PetscFunctionBegin;
3018   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3019   PetscValidType(mat, 1);
3020   PetscAssertPointer(t, 2);
3021   *t = mat->factortype;
3022   PetscFunctionReturn(PETSC_SUCCESS);
3023 }
3024 
3025 /*@
3026   MatSetFactorType - sets the type of factorization a matrix is
3027 
3028   Logically Collective
3029 
3030   Input Parameters:
3031 + mat - the matrix
3032 - 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`
3033 
3034   Level: intermediate
3035 
3036 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3037           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3038 @*/
3039 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3040 {
3041   PetscFunctionBegin;
3042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3043   PetscValidType(mat, 1);
3044   mat->factortype = t;
3045   PetscFunctionReturn(PETSC_SUCCESS);
3046 }
3047 
3048 /*@
3049   MatGetInfo - Returns information about matrix storage (number of
3050   nonzeros, memory, etc.).
3051 
3052   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3053 
3054   Input Parameters:
3055 + mat  - the matrix
3056 - 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)
3057 
3058   Output Parameter:
3059 . info - matrix information context
3060 
3061   Options Database Key:
3062 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3063 
3064   Level: intermediate
3065 
3066   Notes:
3067   The `MatInfo` context contains a variety of matrix data, including
3068   number of nonzeros allocated and used, number of mallocs during
3069   matrix assembly, etc.  Additional information for factored matrices
3070   is provided (such as the fill ratio, number of mallocs during
3071   factorization, etc.).
3072 
3073   Example:
3074   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3075   data within the `MatInfo` context.  For example,
3076 .vb
3077       MatInfo info;
3078       Mat     A;
3079       double  mal, nz_a, nz_u;
3080 
3081       MatGetInfo(A, MAT_LOCAL, &info);
3082       mal  = info.mallocs;
3083       nz_a = info.nz_allocated;
3084 .ve
3085 
3086 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3087 @*/
3088 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3089 {
3090   PetscFunctionBegin;
3091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3092   PetscValidType(mat, 1);
3093   PetscAssertPointer(info, 3);
3094   MatCheckPreallocated(mat, 1);
3095   PetscUseTypeMethod(mat, getinfo, flag, info);
3096   PetscFunctionReturn(PETSC_SUCCESS);
3097 }
3098 
3099 /*
3100    This is used by external packages where it is not easy to get the info from the actual
3101    matrix factorization.
3102 */
3103 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3104 {
3105   PetscFunctionBegin;
3106   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3107   PetscFunctionReturn(PETSC_SUCCESS);
3108 }
3109 
3110 /*@
3111   MatLUFactor - Performs in-place LU factorization of matrix.
3112 
3113   Collective
3114 
3115   Input Parameters:
3116 + mat  - the matrix
3117 . row  - row permutation
3118 . col  - column permutation
3119 - info - options for factorization, includes
3120 .vb
3121           fill - expected fill as ratio of original fill.
3122           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123                    Run with the option -info to determine an optimal value to use
3124 .ve
3125 
3126   Level: developer
3127 
3128   Notes:
3129   Most users should employ the `KSP` interface for linear solvers
3130   instead of working directly with matrix algebra routines such as this.
3131   See, e.g., `KSPCreate()`.
3132 
3133   This changes the state of the matrix to a factored matrix; it cannot be used
3134   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3135 
3136   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3137   when not using `KSP`.
3138 
3139   Developer Note:
3140   The Fortran interface is not autogenerated as the
3141   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3142 
3143 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3144           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3145 @*/
3146 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3147 {
3148   MatFactorInfo tinfo;
3149 
3150   PetscFunctionBegin;
3151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3152   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3153   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3154   if (info) PetscAssertPointer(info, 4);
3155   PetscValidType(mat, 1);
3156   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3157   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3158   MatCheckPreallocated(mat, 1);
3159   if (!info) {
3160     PetscCall(MatFactorInfoInitialize(&tinfo));
3161     info = &tinfo;
3162   }
3163 
3164   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3165   PetscUseTypeMethod(mat, lufactor, row, col, info);
3166   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3167   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3168   PetscFunctionReturn(PETSC_SUCCESS);
3169 }
3170 
3171 /*@
3172   MatILUFactor - Performs in-place ILU factorization of matrix.
3173 
3174   Collective
3175 
3176   Input Parameters:
3177 + mat  - the matrix
3178 . row  - row permutation
3179 . col  - column permutation
3180 - info - structure containing
3181 .vb
3182       levels - number of levels of fill.
3183       expected fill - as ratio of original fill.
3184       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3185                 missing diagonal entries)
3186 .ve
3187 
3188   Level: developer
3189 
3190   Notes:
3191   Most users should employ the `KSP` interface for linear solvers
3192   instead of working directly with matrix algebra routines such as this.
3193   See, e.g., `KSPCreate()`.
3194 
3195   Probably really in-place only when level of fill is zero, otherwise allocates
3196   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3197   when not using `KSP`.
3198 
3199   Developer Note:
3200   The Fortran interface is not autogenerated as the
3201   interface definition cannot be generated correctly [due to MatFactorInfo]
3202 
3203 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3204 @*/
3205 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3206 {
3207   PetscFunctionBegin;
3208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3209   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3210   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3211   PetscAssertPointer(info, 4);
3212   PetscValidType(mat, 1);
3213   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3214   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3215   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3216   MatCheckPreallocated(mat, 1);
3217 
3218   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3219   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3220   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3221   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3222   PetscFunctionReturn(PETSC_SUCCESS);
3223 }
3224 
3225 /*@
3226   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3227   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3228 
3229   Collective
3230 
3231   Input Parameters:
3232 + fact - the factor matrix obtained with `MatGetFactor()`
3233 . mat  - the matrix
3234 . row  - the row permutation
3235 . col  - the column permutation
3236 - info - options for factorization, includes
3237 .vb
3238           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3239           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3240 .ve
3241 
3242   Level: developer
3243 
3244   Notes:
3245   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3246 
3247   Most users should employ the simplified `KSP` interface for linear solvers
3248   instead of working directly with matrix algebra routines such as this.
3249   See, e.g., `KSPCreate()`.
3250 
3251   Developer Note:
3252   The Fortran interface is not autogenerated as the
3253   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3254 
3255 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3256 @*/
3257 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3258 {
3259   MatFactorInfo tinfo;
3260 
3261   PetscFunctionBegin;
3262   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3263   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3264   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3265   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3266   if (info) PetscAssertPointer(info, 5);
3267   PetscValidType(fact, 1);
3268   PetscValidType(mat, 2);
3269   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3270   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3271   MatCheckPreallocated(mat, 2);
3272   if (!info) {
3273     PetscCall(MatFactorInfoInitialize(&tinfo));
3274     info = &tinfo;
3275   }
3276 
3277   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3278   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3279   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3280   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3281   PetscFunctionReturn(PETSC_SUCCESS);
3282 }
3283 
3284 /*@
3285   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3286   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3287 
3288   Collective
3289 
3290   Input Parameters:
3291 + fact - the factor matrix obtained with `MatGetFactor()`
3292 . mat  - the matrix
3293 - info - options for factorization
3294 
3295   Level: developer
3296 
3297   Notes:
3298   See `MatLUFactor()` for in-place factorization.  See
3299   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3300 
3301   Most users should employ the `KSP` interface for linear solvers
3302   instead of working directly with matrix algebra routines such as this.
3303   See, e.g., `KSPCreate()`.
3304 
3305   Developer Note:
3306   The Fortran interface is not autogenerated as the
3307   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3308 
3309 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3310 @*/
3311 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3312 {
3313   MatFactorInfo tinfo;
3314 
3315   PetscFunctionBegin;
3316   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3318   PetscValidType(fact, 1);
3319   PetscValidType(mat, 2);
3320   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3321   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,
3322              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3323 
3324   MatCheckPreallocated(mat, 2);
3325   if (!info) {
3326     PetscCall(MatFactorInfoInitialize(&tinfo));
3327     info = &tinfo;
3328   }
3329 
3330   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3331   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3332   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3333   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3334   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3335   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3336   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3337   PetscFunctionReturn(PETSC_SUCCESS);
3338 }
3339 
3340 /*@
3341   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3342   symmetric matrix.
3343 
3344   Collective
3345 
3346   Input Parameters:
3347 + mat  - the matrix
3348 . perm - row and column permutations
3349 - info - expected fill as ratio of original fill
3350 
3351   Level: developer
3352 
3353   Notes:
3354   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3355   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3356 
3357   Most users should employ the `KSP` interface for linear solvers
3358   instead of working directly with matrix algebra routines such as this.
3359   See, e.g., `KSPCreate()`.
3360 
3361   Developer Note:
3362   The Fortran interface is not autogenerated as the
3363   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3364 
3365 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3366           `MatGetOrdering()`
3367 @*/
3368 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3369 {
3370   MatFactorInfo tinfo;
3371 
3372   PetscFunctionBegin;
3373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3374   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3375   if (info) PetscAssertPointer(info, 3);
3376   PetscValidType(mat, 1);
3377   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3378   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3379   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3380   MatCheckPreallocated(mat, 1);
3381   if (!info) {
3382     PetscCall(MatFactorInfoInitialize(&tinfo));
3383     info = &tinfo;
3384   }
3385 
3386   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3387   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3388   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3389   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3390   PetscFunctionReturn(PETSC_SUCCESS);
3391 }
3392 
3393 /*@
3394   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3395   of a symmetric matrix.
3396 
3397   Collective
3398 
3399   Input Parameters:
3400 + fact - the factor matrix obtained with `MatGetFactor()`
3401 . mat  - the matrix
3402 . perm - row and column permutations
3403 - info - options for factorization, includes
3404 .vb
3405           fill - expected fill as ratio of original fill.
3406           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3407                    Run with the option -info to determine an optimal value to use
3408 .ve
3409 
3410   Level: developer
3411 
3412   Notes:
3413   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3414   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3415 
3416   Most users should employ the `KSP` interface for linear solvers
3417   instead of working directly with matrix algebra routines such as this.
3418   See, e.g., `KSPCreate()`.
3419 
3420   Developer Note:
3421   The Fortran interface is not autogenerated as the
3422   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3423 
3424 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3425           `MatGetOrdering()`
3426 @*/
3427 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3428 {
3429   MatFactorInfo tinfo;
3430 
3431   PetscFunctionBegin;
3432   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3434   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3435   if (info) PetscAssertPointer(info, 4);
3436   PetscValidType(fact, 1);
3437   PetscValidType(mat, 2);
3438   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3439   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3440   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3441   MatCheckPreallocated(mat, 2);
3442   if (!info) {
3443     PetscCall(MatFactorInfoInitialize(&tinfo));
3444     info = &tinfo;
3445   }
3446 
3447   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3448   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3449   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3450   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3451   PetscFunctionReturn(PETSC_SUCCESS);
3452 }
3453 
3454 /*@
3455   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3456   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3457   `MatCholeskyFactorSymbolic()`.
3458 
3459   Collective
3460 
3461   Input Parameters:
3462 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3463 . mat  - the initial matrix that is to be factored
3464 - info - options for factorization
3465 
3466   Level: developer
3467 
3468   Note:
3469   Most users should employ the `KSP` interface for linear solvers
3470   instead of working directly with matrix algebra routines such as this.
3471   See, e.g., `KSPCreate()`.
3472 
3473   Developer Note:
3474   The Fortran interface is not autogenerated as the
3475   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3476 
3477 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3478 @*/
3479 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3480 {
3481   MatFactorInfo tinfo;
3482 
3483   PetscFunctionBegin;
3484   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3486   PetscValidType(fact, 1);
3487   PetscValidType(mat, 2);
3488   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3489   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,
3490              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3491   MatCheckPreallocated(mat, 2);
3492   if (!info) {
3493     PetscCall(MatFactorInfoInitialize(&tinfo));
3494     info = &tinfo;
3495   }
3496 
3497   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3498   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3499   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3500   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3501   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3502   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3503   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3504   PetscFunctionReturn(PETSC_SUCCESS);
3505 }
3506 
3507 /*@
3508   MatQRFactor - Performs in-place QR factorization of matrix.
3509 
3510   Collective
3511 
3512   Input Parameters:
3513 + mat  - the matrix
3514 . col  - column permutation
3515 - info - options for factorization, includes
3516 .vb
3517           fill - expected fill as ratio of original fill.
3518           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3519                    Run with the option -info to determine an optimal value to use
3520 .ve
3521 
3522   Level: developer
3523 
3524   Notes:
3525   Most users should employ the `KSP` interface for linear solvers
3526   instead of working directly with matrix algebra routines such as this.
3527   See, e.g., `KSPCreate()`.
3528 
3529   This changes the state of the matrix to a factored matrix; it cannot be used
3530   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3531 
3532   Developer Note:
3533   The Fortran interface is not autogenerated as the
3534   interface definition cannot be generated correctly [due to MatFactorInfo]
3535 
3536 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3537           `MatSetUnfactored()`
3538 @*/
3539 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3540 {
3541   PetscFunctionBegin;
3542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3543   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3544   if (info) PetscAssertPointer(info, 3);
3545   PetscValidType(mat, 1);
3546   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3547   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3548   MatCheckPreallocated(mat, 1);
3549   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3550   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3551   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3552   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3553   PetscFunctionReturn(PETSC_SUCCESS);
3554 }
3555 
3556 /*@
3557   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3558   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3559 
3560   Collective
3561 
3562   Input Parameters:
3563 + fact - the factor matrix obtained with `MatGetFactor()`
3564 . mat  - the matrix
3565 . col  - column permutation
3566 - info - options for factorization, includes
3567 .vb
3568           fill - expected fill as ratio of original fill.
3569           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3570                    Run with the option -info to determine an optimal value to use
3571 .ve
3572 
3573   Level: developer
3574 
3575   Note:
3576   Most users should employ the `KSP` interface for linear solvers
3577   instead of working directly with matrix algebra routines such as this.
3578   See, e.g., `KSPCreate()`.
3579 
3580   Developer Note:
3581   The Fortran interface is not autogenerated as the
3582   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3583 
3584 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3585 @*/
3586 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3587 {
3588   MatFactorInfo tinfo;
3589 
3590   PetscFunctionBegin;
3591   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3593   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3594   if (info) PetscAssertPointer(info, 4);
3595   PetscValidType(fact, 1);
3596   PetscValidType(mat, 2);
3597   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3598   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3599   MatCheckPreallocated(mat, 2);
3600   if (!info) {
3601     PetscCall(MatFactorInfoInitialize(&tinfo));
3602     info = &tinfo;
3603   }
3604 
3605   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3606   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3607   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3608   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3609   PetscFunctionReturn(PETSC_SUCCESS);
3610 }
3611 
3612 /*@
3613   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3614   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3615 
3616   Collective
3617 
3618   Input Parameters:
3619 + fact - the factor matrix obtained with `MatGetFactor()`
3620 . mat  - the matrix
3621 - info - options for factorization
3622 
3623   Level: developer
3624 
3625   Notes:
3626   See `MatQRFactor()` for in-place factorization.
3627 
3628   Most users should employ the `KSP` interface for linear solvers
3629   instead of working directly with matrix algebra routines such as this.
3630   See, e.g., `KSPCreate()`.
3631 
3632   Developer Note:
3633   The Fortran interface is not autogenerated as the
3634   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3635 
3636 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3637 @*/
3638 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3639 {
3640   MatFactorInfo tinfo;
3641 
3642   PetscFunctionBegin;
3643   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3645   PetscValidType(fact, 1);
3646   PetscValidType(mat, 2);
3647   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3648   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,
3649              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3650 
3651   MatCheckPreallocated(mat, 2);
3652   if (!info) {
3653     PetscCall(MatFactorInfoInitialize(&tinfo));
3654     info = &tinfo;
3655   }
3656 
3657   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3658   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3659   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3660   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3661   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3662   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3663   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3664   PetscFunctionReturn(PETSC_SUCCESS);
3665 }
3666 
3667 /*@
3668   MatSolve - Solves $A x = b$, given a factored matrix.
3669 
3670   Neighbor-wise Collective
3671 
3672   Input Parameters:
3673 + mat - the factored matrix
3674 - b   - the right-hand-side vector
3675 
3676   Output Parameter:
3677 . x - the result vector
3678 
3679   Level: developer
3680 
3681   Notes:
3682   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3683   call `MatSolve`(A,x,x).
3684 
3685   Most users should employ the `KSP` interface for linear solvers
3686   instead of working directly with matrix algebra routines such as this.
3687   See, e.g., `KSPCreate()`.
3688 
3689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3690 @*/
3691 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3692 {
3693   PetscFunctionBegin;
3694   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3695   PetscValidType(mat, 1);
3696   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3697   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3698   PetscCheckSameComm(mat, 1, b, 2);
3699   PetscCheckSameComm(mat, 1, x, 3);
3700   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3701   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);
3702   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);
3703   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);
3704   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3705   MatCheckPreallocated(mat, 1);
3706 
3707   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3708   PetscCall(VecFlag(x, mat->factorerrortype));
3709   if (mat->factorerrortype) {
3710     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3711   } else PetscUseTypeMethod(mat, solve, b, x);
3712   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3713   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3714   PetscFunctionReturn(PETSC_SUCCESS);
3715 }
3716 
3717 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3718 {
3719   Vec      b, x;
3720   PetscInt N, i;
3721   PetscErrorCode (*f)(Mat, Vec, Vec);
3722   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3723 
3724   PetscFunctionBegin;
3725   if (A->factorerrortype) {
3726     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3727     PetscCall(MatSetInf(X));
3728     PetscFunctionReturn(PETSC_SUCCESS);
3729   }
3730   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3731   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3732   PetscCall(MatBoundToCPU(A, &Abound));
3733   if (!Abound) {
3734     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3735     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3736   }
3737 #if PetscDefined(HAVE_CUDA)
3738   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3739   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3740 #elif PetscDefined(HAVE_HIP)
3741   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3742   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3743 #endif
3744   PetscCall(MatGetSize(B, NULL, &N));
3745   for (i = 0; i < N; i++) {
3746     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3747     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3748     PetscCall((*f)(A, b, x));
3749     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3750     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3751   }
3752   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3753   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3754   PetscFunctionReturn(PETSC_SUCCESS);
3755 }
3756 
3757 /*@
3758   MatMatSolve - Solves $A X = B$, given a factored matrix.
3759 
3760   Neighbor-wise Collective
3761 
3762   Input Parameters:
3763 + A - the factored matrix
3764 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3765 
3766   Output Parameter:
3767 . X - the result matrix (dense matrix)
3768 
3769   Level: developer
3770 
3771   Note:
3772   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3773   otherwise, `B` and `X` cannot be the same.
3774 
3775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3776 @*/
3777 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3778 {
3779   PetscFunctionBegin;
3780   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3781   PetscValidType(A, 1);
3782   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3783   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3784   PetscCheckSameComm(A, 1, B, 2);
3785   PetscCheckSameComm(A, 1, X, 3);
3786   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);
3787   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);
3788   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");
3789   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3790   MatCheckPreallocated(A, 1);
3791 
3792   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3793   if (!A->ops->matsolve) {
3794     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3795     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3796   } else PetscUseTypeMethod(A, matsolve, B, X);
3797   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3798   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3799   PetscFunctionReturn(PETSC_SUCCESS);
3800 }
3801 
3802 /*@
3803   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3804 
3805   Neighbor-wise Collective
3806 
3807   Input Parameters:
3808 + A - the factored matrix
3809 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3810 
3811   Output Parameter:
3812 . X - the result matrix (dense matrix)
3813 
3814   Level: developer
3815 
3816   Note:
3817   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3818   call `MatMatSolveTranspose`(A,X,X).
3819 
3820 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3821 @*/
3822 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3823 {
3824   PetscFunctionBegin;
3825   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3826   PetscValidType(A, 1);
3827   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3828   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3829   PetscCheckSameComm(A, 1, B, 2);
3830   PetscCheckSameComm(A, 1, X, 3);
3831   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3832   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);
3833   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);
3834   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);
3835   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");
3836   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3837   MatCheckPreallocated(A, 1);
3838 
3839   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3840   if (!A->ops->matsolvetranspose) {
3841     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3842     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3843   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3844   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3845   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3846   PetscFunctionReturn(PETSC_SUCCESS);
3847 }
3848 
3849 /*@
3850   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3851 
3852   Neighbor-wise Collective
3853 
3854   Input Parameters:
3855 + A  - the factored matrix
3856 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3857 
3858   Output Parameter:
3859 . X - the result matrix (dense matrix)
3860 
3861   Level: developer
3862 
3863   Note:
3864   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
3865   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3866 
3867 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3868 @*/
3869 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3870 {
3871   PetscFunctionBegin;
3872   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3873   PetscValidType(A, 1);
3874   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3875   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3876   PetscCheckSameComm(A, 1, Bt, 2);
3877   PetscCheckSameComm(A, 1, X, 3);
3878 
3879   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3880   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);
3881   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);
3882   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");
3883   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3884   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3885   MatCheckPreallocated(A, 1);
3886 
3887   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3888   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3889   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3890   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3891   PetscFunctionReturn(PETSC_SUCCESS);
3892 }
3893 
3894 /*@
3895   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3896   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3897 
3898   Neighbor-wise Collective
3899 
3900   Input Parameters:
3901 + mat - the factored matrix
3902 - b   - the right-hand-side vector
3903 
3904   Output Parameter:
3905 . x - the result vector
3906 
3907   Level: developer
3908 
3909   Notes:
3910   `MatSolve()` should be used for most applications, as it performs
3911   a forward solve followed by a backward solve.
3912 
3913   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3914   call `MatForwardSolve`(A,x,x).
3915 
3916   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3917   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3918   `MatForwardSolve()` solves $U^T*D y = b$, and
3919   `MatBackwardSolve()` solves $U x = y$.
3920   Thus they do not provide a symmetric preconditioner.
3921 
3922 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3923 @*/
3924 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3925 {
3926   PetscFunctionBegin;
3927   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3928   PetscValidType(mat, 1);
3929   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3930   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3931   PetscCheckSameComm(mat, 1, b, 2);
3932   PetscCheckSameComm(mat, 1, x, 3);
3933   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3934   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);
3935   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);
3936   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);
3937   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3938   MatCheckPreallocated(mat, 1);
3939 
3940   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3941   PetscUseTypeMethod(mat, forwardsolve, b, x);
3942   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3943   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3944   PetscFunctionReturn(PETSC_SUCCESS);
3945 }
3946 
3947 /*@
3948   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3949   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3950 
3951   Neighbor-wise Collective
3952 
3953   Input Parameters:
3954 + mat - the factored matrix
3955 - b   - the right-hand-side vector
3956 
3957   Output Parameter:
3958 . x - the result vector
3959 
3960   Level: developer
3961 
3962   Notes:
3963   `MatSolve()` should be used for most applications, as it performs
3964   a forward solve followed by a backward solve.
3965 
3966   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3967   call `MatBackwardSolve`(A,x,x).
3968 
3969   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3970   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3971   `MatForwardSolve()` solves $U^T*D y = b$, and
3972   `MatBackwardSolve()` solves $U x = y$.
3973   Thus they do not provide a symmetric preconditioner.
3974 
3975 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3976 @*/
3977 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3978 {
3979   PetscFunctionBegin;
3980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3981   PetscValidType(mat, 1);
3982   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3983   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3984   PetscCheckSameComm(mat, 1, b, 2);
3985   PetscCheckSameComm(mat, 1, x, 3);
3986   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3987   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3988   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3989   PetscCheck(mat->rmap->n == 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);
3990   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3991   MatCheckPreallocated(mat, 1);
3992 
3993   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3994   PetscUseTypeMethod(mat, backwardsolve, b, x);
3995   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3996   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3997   PetscFunctionReturn(PETSC_SUCCESS);
3998 }
3999 
4000 /*@
4001   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
4002 
4003   Neighbor-wise Collective
4004 
4005   Input Parameters:
4006 + mat - the factored matrix
4007 . b   - the right-hand-side vector
4008 - y   - the vector to be added to
4009 
4010   Output Parameter:
4011 . x - the result vector
4012 
4013   Level: developer
4014 
4015   Note:
4016   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4017   call `MatSolveAdd`(A,x,y,x).
4018 
4019 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
4020 @*/
4021 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
4022 {
4023   PetscScalar one = 1.0;
4024   Vec         tmp;
4025 
4026   PetscFunctionBegin;
4027   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4028   PetscValidType(mat, 1);
4029   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4030   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4031   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4032   PetscCheckSameComm(mat, 1, b, 2);
4033   PetscCheckSameComm(mat, 1, y, 3);
4034   PetscCheckSameComm(mat, 1, x, 4);
4035   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4036   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);
4037   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);
4038   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);
4039   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);
4040   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);
4041   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4042   MatCheckPreallocated(mat, 1);
4043 
4044   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4045   PetscCall(VecFlag(x, mat->factorerrortype));
4046   if (mat->factorerrortype) {
4047     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4048   } else if (mat->ops->solveadd) {
4049     PetscUseTypeMethod(mat, solveadd, b, y, x);
4050   } else {
4051     /* do the solve then the add manually */
4052     if (x != y) {
4053       PetscCall(MatSolve(mat, b, x));
4054       PetscCall(VecAXPY(x, one, y));
4055     } else {
4056       PetscCall(VecDuplicate(x, &tmp));
4057       PetscCall(VecCopy(x, tmp));
4058       PetscCall(MatSolve(mat, b, x));
4059       PetscCall(VecAXPY(x, one, tmp));
4060       PetscCall(VecDestroy(&tmp));
4061     }
4062   }
4063   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4064   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4065   PetscFunctionReturn(PETSC_SUCCESS);
4066 }
4067 
4068 /*@
4069   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4070 
4071   Neighbor-wise Collective
4072 
4073   Input Parameters:
4074 + mat - the factored matrix
4075 - b   - the right-hand-side vector
4076 
4077   Output Parameter:
4078 . x - the result vector
4079 
4080   Level: developer
4081 
4082   Notes:
4083   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4084   call `MatSolveTranspose`(A,x,x).
4085 
4086   Most users should employ the `KSP` interface for linear solvers
4087   instead of working directly with matrix algebra routines such as this.
4088   See, e.g., `KSPCreate()`.
4089 
4090 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4091 @*/
4092 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4093 {
4094   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4095 
4096   PetscFunctionBegin;
4097   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4098   PetscValidType(mat, 1);
4099   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4100   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4101   PetscCheckSameComm(mat, 1, b, 2);
4102   PetscCheckSameComm(mat, 1, x, 3);
4103   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4104   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);
4105   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);
4106   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4107   MatCheckPreallocated(mat, 1);
4108   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4109   PetscCall(VecFlag(x, mat->factorerrortype));
4110   if (mat->factorerrortype) {
4111     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4112   } else {
4113     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4114     PetscCall((*f)(mat, b, x));
4115   }
4116   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4117   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4118   PetscFunctionReturn(PETSC_SUCCESS);
4119 }
4120 
4121 /*@
4122   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4123   factored matrix.
4124 
4125   Neighbor-wise Collective
4126 
4127   Input Parameters:
4128 + mat - the factored matrix
4129 . b   - the right-hand-side vector
4130 - y   - the vector to be added to
4131 
4132   Output Parameter:
4133 . x - the result vector
4134 
4135   Level: developer
4136 
4137   Note:
4138   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4139   call `MatSolveTransposeAdd`(A,x,y,x).
4140 
4141 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4142 @*/
4143 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4144 {
4145   PetscScalar one = 1.0;
4146   Vec         tmp;
4147   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4148 
4149   PetscFunctionBegin;
4150   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4151   PetscValidType(mat, 1);
4152   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4153   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4154   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4155   PetscCheckSameComm(mat, 1, b, 2);
4156   PetscCheckSameComm(mat, 1, y, 3);
4157   PetscCheckSameComm(mat, 1, x, 4);
4158   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4159   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);
4160   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);
4161   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);
4162   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);
4163   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4164   MatCheckPreallocated(mat, 1);
4165 
4166   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4167   PetscCall(VecFlag(x, mat->factorerrortype));
4168   if (mat->factorerrortype) {
4169     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4170   } else if (f) {
4171     PetscCall((*f)(mat, b, y, x));
4172   } else {
4173     /* do the solve then the add manually */
4174     if (x != y) {
4175       PetscCall(MatSolveTranspose(mat, b, x));
4176       PetscCall(VecAXPY(x, one, y));
4177     } else {
4178       PetscCall(VecDuplicate(x, &tmp));
4179       PetscCall(VecCopy(x, tmp));
4180       PetscCall(MatSolveTranspose(mat, b, x));
4181       PetscCall(VecAXPY(x, one, tmp));
4182       PetscCall(VecDestroy(&tmp));
4183     }
4184   }
4185   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4186   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4187   PetscFunctionReturn(PETSC_SUCCESS);
4188 }
4189 
4190 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4191 /*@
4192   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4193 
4194   Neighbor-wise Collective
4195 
4196   Input Parameters:
4197 + mat   - the matrix
4198 . b     - the right-hand side
4199 . omega - the relaxation factor
4200 . flag  - flag indicating the type of SOR (see below)
4201 . shift - diagonal shift
4202 . its   - the number of iterations
4203 - lits  - the number of local iterations
4204 
4205   Output Parameter:
4206 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4207 
4208   SOR Flags:
4209 +     `SOR_FORWARD_SWEEP` - forward SOR
4210 .     `SOR_BACKWARD_SWEEP` - backward SOR
4211 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4212 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4213 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4214 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4215 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4216 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4217   upper/lower triangular part of matrix to
4218   vector (with omega)
4219 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4220 
4221   Level: developer
4222 
4223   Notes:
4224   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4225   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4226   on each processor.
4227 
4228   Application programmers will not generally use `MatSOR()` directly,
4229   but instead will employ the `KSP`/`PC` interface.
4230 
4231   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4232 
4233   Most users should employ the `KSP` interface for linear solvers
4234   instead of working directly with matrix algebra routines such as this.
4235   See, e.g., `KSPCreate()`.
4236 
4237   Vectors `x` and `b` CANNOT be the same
4238 
4239   The flags are implemented as bitwise inclusive or operations.
4240   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4241   to specify a zero initial guess for SSOR.
4242 
4243   Developer Note:
4244   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4245 
4246 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4247 @*/
4248 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4249 {
4250   PetscFunctionBegin;
4251   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4252   PetscValidType(mat, 1);
4253   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4254   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4255   PetscCheckSameComm(mat, 1, b, 2);
4256   PetscCheckSameComm(mat, 1, x, 8);
4257   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4258   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4259   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);
4260   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);
4261   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);
4262   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4263   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4264   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4265 
4266   MatCheckPreallocated(mat, 1);
4267   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4268   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4269   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4270   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4271   PetscFunctionReturn(PETSC_SUCCESS);
4272 }
4273 
4274 /*
4275       Default matrix copy routine.
4276 */
4277 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4278 {
4279   PetscInt           i, rstart = 0, rend = 0, nz;
4280   const PetscInt    *cwork;
4281   const PetscScalar *vwork;
4282 
4283   PetscFunctionBegin;
4284   if (B->assembled) PetscCall(MatZeroEntries(B));
4285   if (str == SAME_NONZERO_PATTERN) {
4286     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4287     for (i = rstart; i < rend; i++) {
4288       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4289       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4290       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4291     }
4292   } else {
4293     PetscCall(MatAYPX(B, 0.0, A, str));
4294   }
4295   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4296   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4297   PetscFunctionReturn(PETSC_SUCCESS);
4298 }
4299 
4300 /*@
4301   MatCopy - Copies a matrix to another matrix.
4302 
4303   Collective
4304 
4305   Input Parameters:
4306 + A   - the matrix
4307 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4308 
4309   Output Parameter:
4310 . B - where the copy is put
4311 
4312   Level: intermediate
4313 
4314   Notes:
4315   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4316 
4317   `MatCopy()` copies the matrix entries of a matrix to another existing
4318   matrix (after first zeroing the second matrix).  A related routine is
4319   `MatConvert()`, which first creates a new matrix and then copies the data.
4320 
4321 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4322 @*/
4323 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4324 {
4325   PetscInt i;
4326 
4327   PetscFunctionBegin;
4328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4329   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4330   PetscValidType(A, 1);
4331   PetscValidType(B, 2);
4332   PetscCheckSameComm(A, 1, B, 2);
4333   MatCheckPreallocated(B, 2);
4334   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4335   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4336   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,
4337              A->cmap->N, B->cmap->N);
4338   MatCheckPreallocated(A, 1);
4339   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4340 
4341   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4342   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4343   else PetscCall(MatCopy_Basic(A, B, str));
4344 
4345   B->stencil.dim = A->stencil.dim;
4346   B->stencil.noc = A->stencil.noc;
4347   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4348     B->stencil.dims[i]   = A->stencil.dims[i];
4349     B->stencil.starts[i] = A->stencil.starts[i];
4350   }
4351 
4352   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4353   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4354   PetscFunctionReturn(PETSC_SUCCESS);
4355 }
4356 
4357 /*@
4358   MatConvert - Converts a matrix to another matrix, either of the same
4359   or different type.
4360 
4361   Collective
4362 
4363   Input Parameters:
4364 + mat     - the matrix
4365 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4366             same type as the original matrix.
4367 - reuse   - denotes if the destination matrix is to be created or reused.
4368             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
4369             `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).
4370 
4371   Output Parameter:
4372 . M - pointer to place new matrix
4373 
4374   Level: intermediate
4375 
4376   Notes:
4377   `MatConvert()` first creates a new matrix and then copies the data from
4378   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4379   entries of one matrix to another already existing matrix context.
4380 
4381   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4382   the MPI communicator of the generated matrix is always the same as the communicator
4383   of the input matrix.
4384 
4385 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4386 @*/
4387 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4388 {
4389   PetscBool  sametype, issame, flg;
4390   PetscBool3 issymmetric, ishermitian;
4391   char       convname[256], mtype[256];
4392   Mat        B;
4393 
4394   PetscFunctionBegin;
4395   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4396   PetscValidType(mat, 1);
4397   PetscAssertPointer(M, 4);
4398   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4399   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4400   MatCheckPreallocated(mat, 1);
4401 
4402   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4403   if (flg) newtype = mtype;
4404 
4405   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4406   PetscCall(PetscStrcmp(newtype, "same", &issame));
4407   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4408   if (reuse == MAT_REUSE_MATRIX) {
4409     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4410     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4411   }
4412 
4413   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4414     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4415     PetscFunctionReturn(PETSC_SUCCESS);
4416   }
4417 
4418   /* Cache Mat options because some converters use MatHeaderReplace  */
4419   issymmetric = mat->symmetric;
4420   ishermitian = mat->hermitian;
4421 
4422   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4423     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4424     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4425   } else {
4426     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4427     const char *prefix[3]                                 = {"seq", "mpi", ""};
4428     PetscInt    i;
4429     /*
4430        Order of precedence:
4431        0) See if newtype is a superclass of the current matrix.
4432        1) See if a specialized converter is known to the current matrix.
4433        2) See if a specialized converter is known to the desired matrix class.
4434        3) See if a good general converter is registered for the desired class
4435           (as of 6/27/03 only MATMPIADJ falls into this category).
4436        4) See if a good general converter is known for the current matrix.
4437        5) Use a really basic converter.
4438     */
4439 
4440     /* 0) See if newtype is a superclass of the current matrix.
4441           i.e mat is mpiaij and newtype is aij */
4442     for (i = 0; i < 2; i++) {
4443       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4444       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4445       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4446       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4447       if (flg) {
4448         if (reuse == MAT_INPLACE_MATRIX) {
4449           PetscCall(PetscInfo(mat, "Early return\n"));
4450           PetscFunctionReturn(PETSC_SUCCESS);
4451         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4452           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4453           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4454           PetscFunctionReturn(PETSC_SUCCESS);
4455         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4456           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4457           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4458           PetscFunctionReturn(PETSC_SUCCESS);
4459         }
4460       }
4461     }
4462     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4463     for (i = 0; i < 3; i++) {
4464       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4465       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4466       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4467       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4468       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4469       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4470       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4471       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4472       if (conv) goto foundconv;
4473     }
4474 
4475     /* 2)  See if a specialized converter is known to the desired matrix class. */
4476     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4477     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4478     PetscCall(MatSetType(B, newtype));
4479     for (i = 0; i < 3; i++) {
4480       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4481       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4482       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4483       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4484       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4485       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4486       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4487       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4488       if (conv) {
4489         PetscCall(MatDestroy(&B));
4490         goto foundconv;
4491       }
4492     }
4493 
4494     /* 3) See if a good general converter is registered for the desired class */
4495     conv = B->ops->convertfrom;
4496     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4497     PetscCall(MatDestroy(&B));
4498     if (conv) goto foundconv;
4499 
4500     /* 4) See if a good general converter is known for the current matrix */
4501     if (mat->ops->convert) conv = mat->ops->convert;
4502     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4503     if (conv) goto foundconv;
4504 
4505     /* 5) Use a really basic converter. */
4506     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4507     conv = MatConvert_Basic;
4508 
4509   foundconv:
4510     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4511     PetscCall((*conv)(mat, newtype, reuse, M));
4512     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4513       /* the block sizes must be same if the mappings are copied over */
4514       (*M)->rmap->bs = mat->rmap->bs;
4515       (*M)->cmap->bs = mat->cmap->bs;
4516       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4517       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4518       (*M)->rmap->mapping = mat->rmap->mapping;
4519       (*M)->cmap->mapping = mat->cmap->mapping;
4520     }
4521     (*M)->stencil.dim = mat->stencil.dim;
4522     (*M)->stencil.noc = mat->stencil.noc;
4523     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4524       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4525       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4526     }
4527     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4528   }
4529   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4530 
4531   /* Copy Mat options */
4532   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4533   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4534   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4535   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4536   PetscFunctionReturn(PETSC_SUCCESS);
4537 }
4538 
4539 /*@
4540   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4541 
4542   Not Collective
4543 
4544   Input Parameter:
4545 . mat - the matrix, must be a factored matrix
4546 
4547   Output Parameter:
4548 . type - the string name of the package (do not free this string)
4549 
4550   Level: intermediate
4551 
4552   Fortran Note:
4553   Pass in an empty string that is long enough and the package name will be copied into it.
4554 
4555 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4556 @*/
4557 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4558 {
4559   PetscErrorCode (*conv)(Mat, MatSolverType *);
4560 
4561   PetscFunctionBegin;
4562   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4563   PetscValidType(mat, 1);
4564   PetscAssertPointer(type, 2);
4565   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4566   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4567   if (conv) PetscCall((*conv)(mat, type));
4568   else *type = MATSOLVERPETSC;
4569   PetscFunctionReturn(PETSC_SUCCESS);
4570 }
4571 
4572 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4573 struct _MatSolverTypeForSpecifcType {
4574   MatType mtype;
4575   /* no entry for MAT_FACTOR_NONE */
4576   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4577   MatSolverTypeForSpecifcType next;
4578 };
4579 
4580 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4581 struct _MatSolverTypeHolder {
4582   char                       *name;
4583   MatSolverTypeForSpecifcType handlers;
4584   MatSolverTypeHolder         next;
4585 };
4586 
4587 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4588 
4589 /*@C
4590   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4591 
4592   Logically Collective, No Fortran Support
4593 
4594   Input Parameters:
4595 + package      - name of the package, for example petsc or superlu
4596 . mtype        - the matrix type that works with this package
4597 . ftype        - the type of factorization supported by the package
4598 - createfactor - routine that will create the factored matrix ready to be used
4599 
4600   Level: developer
4601 
4602 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4603   `MatGetFactor()`
4604 @*/
4605 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4606 {
4607   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4608   PetscBool                   flg;
4609   MatSolverTypeForSpecifcType inext, iprev = NULL;
4610 
4611   PetscFunctionBegin;
4612   PetscCall(MatInitializePackage());
4613   if (!next) {
4614     PetscCall(PetscNew(&MatSolverTypeHolders));
4615     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4616     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4617     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4618     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4619     PetscFunctionReturn(PETSC_SUCCESS);
4620   }
4621   while (next) {
4622     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4623     if (flg) {
4624       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4625       inext = next->handlers;
4626       while (inext) {
4627         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4628         if (flg) {
4629           inext->createfactor[(int)ftype - 1] = createfactor;
4630           PetscFunctionReturn(PETSC_SUCCESS);
4631         }
4632         iprev = inext;
4633         inext = inext->next;
4634       }
4635       PetscCall(PetscNew(&iprev->next));
4636       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4637       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4638       PetscFunctionReturn(PETSC_SUCCESS);
4639     }
4640     prev = next;
4641     next = next->next;
4642   }
4643   PetscCall(PetscNew(&prev->next));
4644   PetscCall(PetscStrallocpy(package, &prev->next->name));
4645   PetscCall(PetscNew(&prev->next->handlers));
4646   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4647   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4648   PetscFunctionReturn(PETSC_SUCCESS);
4649 }
4650 
4651 /*@C
4652   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4653 
4654   Input Parameters:
4655 + 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
4656 . ftype - the type of factorization supported by the type
4657 - mtype - the matrix type that works with this type
4658 
4659   Output Parameters:
4660 + foundtype    - `PETSC_TRUE` if the type was registered
4661 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4662 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4663 
4664   Calling sequence of `createfactor`:
4665 + A     - the matrix providing the factor matrix
4666 . ftype - the `MatFactorType` of the factor requested
4667 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4668 
4669   Level: developer
4670 
4671   Note:
4672   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4673   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4674   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4675 
4676 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4677           `MatInitializePackage()`
4678 @*/
4679 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4680 {
4681   MatSolverTypeHolder         next = MatSolverTypeHolders;
4682   PetscBool                   flg;
4683   MatSolverTypeForSpecifcType inext;
4684 
4685   PetscFunctionBegin;
4686   if (foundtype) *foundtype = PETSC_FALSE;
4687   if (foundmtype) *foundmtype = PETSC_FALSE;
4688   if (createfactor) *createfactor = NULL;
4689 
4690   if (type) {
4691     while (next) {
4692       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4693       if (flg) {
4694         if (foundtype) *foundtype = PETSC_TRUE;
4695         inext = next->handlers;
4696         while (inext) {
4697           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4698           if (flg) {
4699             if (foundmtype) *foundmtype = PETSC_TRUE;
4700             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4701             PetscFunctionReturn(PETSC_SUCCESS);
4702           }
4703           inext = inext->next;
4704         }
4705       }
4706       next = next->next;
4707     }
4708   } else {
4709     while (next) {
4710       inext = next->handlers;
4711       while (inext) {
4712         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4713         if (flg && inext->createfactor[(int)ftype - 1]) {
4714           if (foundtype) *foundtype = PETSC_TRUE;
4715           if (foundmtype) *foundmtype = PETSC_TRUE;
4716           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4717           PetscFunctionReturn(PETSC_SUCCESS);
4718         }
4719         inext = inext->next;
4720       }
4721       next = next->next;
4722     }
4723     /* try with base classes inext->mtype */
4724     next = MatSolverTypeHolders;
4725     while (next) {
4726       inext = next->handlers;
4727       while (inext) {
4728         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4729         if (flg && inext->createfactor[(int)ftype - 1]) {
4730           if (foundtype) *foundtype = PETSC_TRUE;
4731           if (foundmtype) *foundmtype = PETSC_TRUE;
4732           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4733           PetscFunctionReturn(PETSC_SUCCESS);
4734         }
4735         inext = inext->next;
4736       }
4737       next = next->next;
4738     }
4739   }
4740   PetscFunctionReturn(PETSC_SUCCESS);
4741 }
4742 
4743 PetscErrorCode MatSolverTypeDestroy(void)
4744 {
4745   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4746   MatSolverTypeForSpecifcType inext, iprev;
4747 
4748   PetscFunctionBegin;
4749   while (next) {
4750     PetscCall(PetscFree(next->name));
4751     inext = next->handlers;
4752     while (inext) {
4753       PetscCall(PetscFree(inext->mtype));
4754       iprev = inext;
4755       inext = inext->next;
4756       PetscCall(PetscFree(iprev));
4757     }
4758     prev = next;
4759     next = next->next;
4760     PetscCall(PetscFree(prev));
4761   }
4762   MatSolverTypeHolders = NULL;
4763   PetscFunctionReturn(PETSC_SUCCESS);
4764 }
4765 
4766 /*@
4767   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4768 
4769   Logically Collective
4770 
4771   Input Parameter:
4772 . mat - the matrix
4773 
4774   Output Parameter:
4775 . flg - `PETSC_TRUE` if uses the ordering
4776 
4777   Level: developer
4778 
4779   Note:
4780   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4781   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4782 
4783 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4784 @*/
4785 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4786 {
4787   PetscFunctionBegin;
4788   *flg = mat->canuseordering;
4789   PetscFunctionReturn(PETSC_SUCCESS);
4790 }
4791 
4792 /*@
4793   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4794 
4795   Logically Collective
4796 
4797   Input Parameters:
4798 + mat   - the matrix obtained with `MatGetFactor()`
4799 - ftype - the factorization type to be used
4800 
4801   Output Parameter:
4802 . otype - the preferred ordering type
4803 
4804   Level: developer
4805 
4806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4807 @*/
4808 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4809 {
4810   PetscFunctionBegin;
4811   *otype = mat->preferredordering[ftype];
4812   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4813   PetscFunctionReturn(PETSC_SUCCESS);
4814 }
4815 
4816 /*@
4817   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4818 
4819   Collective
4820 
4821   Input Parameters:
4822 + mat   - the matrix
4823 . 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
4824           the other criteria is returned
4825 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4826 
4827   Output Parameter:
4828 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4829 
4830   Options Database Keys:
4831 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4832 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4833                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4834 
4835   Level: intermediate
4836 
4837   Notes:
4838   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4839   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4840 
4841   Users usually access the factorization solvers via `KSP`
4842 
4843   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4844   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
4845 
4846   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4847   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4848   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4849 
4850   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4851   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4852   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4853 
4854   Developer Note:
4855   This should actually be called `MatCreateFactor()` since it creates a new factor object
4856 
4857 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4858           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4859           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4860 @*/
4861 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4862 {
4863   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4864   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4865 
4866   PetscFunctionBegin;
4867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4868   PetscValidType(mat, 1);
4869 
4870   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4871   MatCheckPreallocated(mat, 1);
4872 
4873   PetscCall(MatIsShell(mat, &shell));
4874   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4875   if (hasop) {
4876     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4877     PetscFunctionReturn(PETSC_SUCCESS);
4878   }
4879 
4880   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4881   if (!foundtype) {
4882     if (type) {
4883       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],
4884               ((PetscObject)mat)->type_name, type);
4885     } else {
4886       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);
4887     }
4888   }
4889   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4890   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);
4891 
4892   PetscCall((*conv)(mat, ftype, f));
4893   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4894   PetscFunctionReturn(PETSC_SUCCESS);
4895 }
4896 
4897 /*@
4898   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4899 
4900   Not Collective
4901 
4902   Input Parameters:
4903 + mat   - the matrix
4904 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4905 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4906 
4907   Output Parameter:
4908 . flg - PETSC_TRUE if the factorization is available
4909 
4910   Level: intermediate
4911 
4912   Notes:
4913   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4914   such as pastix, superlu, mumps etc.
4915 
4916   PETSc must have been ./configure to use the external solver, using the option --download-package
4917 
4918   Developer Note:
4919   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4920 
4921 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4922           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4923 @*/
4924 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4925 {
4926   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4927 
4928   PetscFunctionBegin;
4929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4930   PetscAssertPointer(flg, 4);
4931 
4932   *flg = PETSC_FALSE;
4933   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4934 
4935   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4936   MatCheckPreallocated(mat, 1);
4937 
4938   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4939   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4940   PetscFunctionReturn(PETSC_SUCCESS);
4941 }
4942 
4943 /*@
4944   MatDuplicate - Duplicates a matrix including the non-zero structure.
4945 
4946   Collective
4947 
4948   Input Parameters:
4949 + mat - the matrix
4950 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4951         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4952 
4953   Output Parameter:
4954 . M - pointer to place new matrix
4955 
4956   Level: intermediate
4957 
4958   Notes:
4959   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4960 
4961   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4962 
4963   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.
4964 
4965   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4966   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4967   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4968 
4969 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4970 @*/
4971 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4972 {
4973   Mat         B;
4974   VecType     vtype;
4975   PetscInt    i;
4976   PetscObject dm, container_h, container_d;
4977   void (*viewf)(void);
4978 
4979   PetscFunctionBegin;
4980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4981   PetscValidType(mat, 1);
4982   PetscAssertPointer(M, 3);
4983   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4984   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4985   MatCheckPreallocated(mat, 1);
4986 
4987   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4988   PetscUseTypeMethod(mat, duplicate, op, M);
4989   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4990   B = *M;
4991 
4992   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4993   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4994   PetscCall(MatGetVecType(mat, &vtype));
4995   PetscCall(MatSetVecType(B, vtype));
4996 
4997   B->stencil.dim = mat->stencil.dim;
4998   B->stencil.noc = mat->stencil.noc;
4999   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
5000     B->stencil.dims[i]   = mat->stencil.dims[i];
5001     B->stencil.starts[i] = mat->stencil.starts[i];
5002   }
5003 
5004   B->nooffproczerorows = mat->nooffproczerorows;
5005   B->nooffprocentries  = mat->nooffprocentries;
5006 
5007   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
5008   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
5009   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
5010   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
5011   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
5012   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
5013   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
5014   PetscCall(PetscObjectStateIncrease((PetscObject)B));
5015   PetscFunctionReturn(PETSC_SUCCESS);
5016 }
5017 
5018 /*@
5019   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
5020 
5021   Logically Collective
5022 
5023   Input Parameter:
5024 . mat - the matrix
5025 
5026   Output Parameter:
5027 . v - the diagonal of the matrix
5028 
5029   Level: intermediate
5030 
5031   Note:
5032   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5033   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5034   is larger than `ndiag`, the values of the remaining entries are unspecified.
5035 
5036   Currently only correct in parallel for square matrices.
5037 
5038 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5039 @*/
5040 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5041 {
5042   PetscFunctionBegin;
5043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5044   PetscValidType(mat, 1);
5045   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5046   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5047   MatCheckPreallocated(mat, 1);
5048   if (PetscDefined(USE_DEBUG)) {
5049     PetscInt nv, row, col, ndiag;
5050 
5051     PetscCall(VecGetLocalSize(v, &nv));
5052     PetscCall(MatGetLocalSize(mat, &row, &col));
5053     ndiag = PetscMin(row, col);
5054     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);
5055   }
5056 
5057   PetscUseTypeMethod(mat, getdiagonal, v);
5058   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5059   PetscFunctionReturn(PETSC_SUCCESS);
5060 }
5061 
5062 /*@
5063   MatGetRowMin - Gets the minimum value (of the real part) of each
5064   row of the matrix
5065 
5066   Logically Collective
5067 
5068   Input Parameter:
5069 . mat - the matrix
5070 
5071   Output Parameters:
5072 + v   - the vector for storing the maximums
5073 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5074 
5075   Level: intermediate
5076 
5077   Note:
5078   The result of this call are the same as if one converted the matrix to dense format
5079   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5080 
5081   This code is only implemented for a couple of matrix formats.
5082 
5083 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5084           `MatGetRowMax()`
5085 @*/
5086 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5087 {
5088   PetscFunctionBegin;
5089   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5090   PetscValidType(mat, 1);
5091   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5092   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5093 
5094   if (!mat->cmap->N) {
5095     PetscCall(VecSet(v, PETSC_MAX_REAL));
5096     if (idx) {
5097       PetscInt i, m = mat->rmap->n;
5098       for (i = 0; i < m; i++) idx[i] = -1;
5099     }
5100   } else {
5101     MatCheckPreallocated(mat, 1);
5102   }
5103   PetscUseTypeMethod(mat, getrowmin, v, idx);
5104   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5105   PetscFunctionReturn(PETSC_SUCCESS);
5106 }
5107 
5108 /*@
5109   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5110   row of the matrix
5111 
5112   Logically Collective
5113 
5114   Input Parameter:
5115 . mat - the matrix
5116 
5117   Output Parameters:
5118 + v   - the vector for storing the minimums
5119 - idx - the indices of the column found for each row (or `NULL` if not needed)
5120 
5121   Level: intermediate
5122 
5123   Notes:
5124   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5125   row is 0 (the first column).
5126 
5127   This code is only implemented for a couple of matrix formats.
5128 
5129 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5130 @*/
5131 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5132 {
5133   PetscFunctionBegin;
5134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5135   PetscValidType(mat, 1);
5136   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5137   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5138   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5139 
5140   if (!mat->cmap->N) {
5141     PetscCall(VecSet(v, 0.0));
5142     if (idx) {
5143       PetscInt i, m = mat->rmap->n;
5144       for (i = 0; i < m; i++) idx[i] = -1;
5145     }
5146   } else {
5147     MatCheckPreallocated(mat, 1);
5148     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5149     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5150   }
5151   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5152   PetscFunctionReturn(PETSC_SUCCESS);
5153 }
5154 
5155 /*@
5156   MatGetRowMax - Gets the maximum value (of the real part) of each
5157   row of the matrix
5158 
5159   Logically Collective
5160 
5161   Input Parameter:
5162 . mat - the matrix
5163 
5164   Output Parameters:
5165 + v   - the vector for storing the maximums
5166 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5167 
5168   Level: intermediate
5169 
5170   Notes:
5171   The result of this call are the same as if one converted the matrix to dense format
5172   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5173 
5174   This code is only implemented for a couple of matrix formats.
5175 
5176 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5177 @*/
5178 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5179 {
5180   PetscFunctionBegin;
5181   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5182   PetscValidType(mat, 1);
5183   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5184   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5185 
5186   if (!mat->cmap->N) {
5187     PetscCall(VecSet(v, PETSC_MIN_REAL));
5188     if (idx) {
5189       PetscInt i, m = mat->rmap->n;
5190       for (i = 0; i < m; i++) idx[i] = -1;
5191     }
5192   } else {
5193     MatCheckPreallocated(mat, 1);
5194     PetscUseTypeMethod(mat, getrowmax, v, idx);
5195   }
5196   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5197   PetscFunctionReturn(PETSC_SUCCESS);
5198 }
5199 
5200 /*@
5201   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5202   row of the matrix
5203 
5204   Logically Collective
5205 
5206   Input Parameter:
5207 . mat - the matrix
5208 
5209   Output Parameters:
5210 + v   - the vector for storing the maximums
5211 - idx - the indices of the column found for each row (or `NULL` if not needed)
5212 
5213   Level: intermediate
5214 
5215   Notes:
5216   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5217   row is 0 (the first column).
5218 
5219   This code is only implemented for a couple of matrix formats.
5220 
5221 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5222 @*/
5223 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5224 {
5225   PetscFunctionBegin;
5226   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5227   PetscValidType(mat, 1);
5228   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5229   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5230 
5231   if (!mat->cmap->N) {
5232     PetscCall(VecSet(v, 0.0));
5233     if (idx) {
5234       PetscInt i, m = mat->rmap->n;
5235       for (i = 0; i < m; i++) idx[i] = -1;
5236     }
5237   } else {
5238     MatCheckPreallocated(mat, 1);
5239     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5240     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5241   }
5242   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5243   PetscFunctionReturn(PETSC_SUCCESS);
5244 }
5245 
5246 /*@
5247   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5248 
5249   Logically Collective
5250 
5251   Input Parameter:
5252 . mat - the matrix
5253 
5254   Output Parameter:
5255 . v - the vector for storing the sum
5256 
5257   Level: intermediate
5258 
5259   This code is only implemented for a couple of matrix formats.
5260 
5261 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5262 @*/
5263 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5264 {
5265   PetscFunctionBegin;
5266   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5267   PetscValidType(mat, 1);
5268   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5269   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5270 
5271   if (!mat->cmap->N) {
5272     PetscCall(VecSet(v, 0.0));
5273   } else {
5274     MatCheckPreallocated(mat, 1);
5275     PetscUseTypeMethod(mat, getrowsumabs, v);
5276   }
5277   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5278   PetscFunctionReturn(PETSC_SUCCESS);
5279 }
5280 
5281 /*@
5282   MatGetRowSum - Gets the sum of each row of the matrix
5283 
5284   Logically or Neighborhood Collective
5285 
5286   Input Parameter:
5287 . mat - the matrix
5288 
5289   Output Parameter:
5290 . v - the vector for storing the sum of rows
5291 
5292   Level: intermediate
5293 
5294   Note:
5295   This code is slow since it is not currently specialized for different formats
5296 
5297 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5298 @*/
5299 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5300 {
5301   Vec ones;
5302 
5303   PetscFunctionBegin;
5304   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5305   PetscValidType(mat, 1);
5306   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5307   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5308   MatCheckPreallocated(mat, 1);
5309   PetscCall(MatCreateVecs(mat, &ones, NULL));
5310   PetscCall(VecSet(ones, 1.));
5311   PetscCall(MatMult(mat, ones, v));
5312   PetscCall(VecDestroy(&ones));
5313   PetscFunctionReturn(PETSC_SUCCESS);
5314 }
5315 
5316 /*@
5317   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5318   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5319 
5320   Collective
5321 
5322   Input Parameter:
5323 . mat - the matrix to provide the transpose
5324 
5325   Output Parameter:
5326 . 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
5327 
5328   Level: advanced
5329 
5330   Note:
5331   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
5332   routine allows bypassing that call.
5333 
5334 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5335 @*/
5336 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5337 {
5338   MatParentState *rb = NULL;
5339 
5340   PetscFunctionBegin;
5341   PetscCall(PetscNew(&rb));
5342   rb->id    = ((PetscObject)mat)->id;
5343   rb->state = 0;
5344   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5345   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5346   PetscFunctionReturn(PETSC_SUCCESS);
5347 }
5348 
5349 /*@
5350   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5351 
5352   Collective
5353 
5354   Input Parameters:
5355 + mat   - the matrix to transpose
5356 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5357 
5358   Output Parameter:
5359 . B - the transpose of the matrix
5360 
5361   Level: intermediate
5362 
5363   Notes:
5364   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5365 
5366   `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
5367   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5368 
5369   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.
5370 
5371   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5372   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5373 
5374   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5375 
5376   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5377 
5378 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5379           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5380 @*/
5381 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5382 {
5383   PetscContainer  rB = NULL;
5384   MatParentState *rb = NULL;
5385 
5386   PetscFunctionBegin;
5387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5388   PetscValidType(mat, 1);
5389   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5390   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5391   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5392   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5393   MatCheckPreallocated(mat, 1);
5394   if (reuse == MAT_REUSE_MATRIX) {
5395     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5396     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5397     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5398     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5399     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5400   }
5401 
5402   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5403   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5404     PetscUseTypeMethod(mat, transpose, reuse, B);
5405     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5406   }
5407   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5408 
5409   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5410   if (reuse != MAT_INPLACE_MATRIX) {
5411     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5412     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5413     rb->state        = ((PetscObject)mat)->state;
5414     rb->nonzerostate = mat->nonzerostate;
5415   }
5416   PetscFunctionReturn(PETSC_SUCCESS);
5417 }
5418 
5419 /*@
5420   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5421 
5422   Collective
5423 
5424   Input Parameter:
5425 . A - the matrix to transpose
5426 
5427   Output Parameter:
5428 . 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
5429       numerical portion.
5430 
5431   Level: intermediate
5432 
5433   Note:
5434   This is not supported for many matrix types, use `MatTranspose()` in those cases
5435 
5436 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5437 @*/
5438 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5439 {
5440   PetscFunctionBegin;
5441   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5442   PetscValidType(A, 1);
5443   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5444   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5445   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5446   PetscUseTypeMethod(A, transposesymbolic, B);
5447   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5448 
5449   PetscCall(MatTransposeSetPrecursor(A, *B));
5450   PetscFunctionReturn(PETSC_SUCCESS);
5451 }
5452 
5453 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5454 {
5455   PetscContainer  rB;
5456   MatParentState *rb;
5457 
5458   PetscFunctionBegin;
5459   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5460   PetscValidType(A, 1);
5461   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5462   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5463   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5464   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5465   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5466   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5467   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5468   PetscFunctionReturn(PETSC_SUCCESS);
5469 }
5470 
5471 /*@
5472   MatIsTranspose - Test whether a matrix is another one's transpose,
5473   or its own, in which case it tests symmetry.
5474 
5475   Collective
5476 
5477   Input Parameters:
5478 + A   - the matrix to test
5479 . B   - the matrix to test against, this can equal the first parameter
5480 - tol - tolerance, differences between entries smaller than this are counted as zero
5481 
5482   Output Parameter:
5483 . flg - the result
5484 
5485   Level: intermediate
5486 
5487   Notes:
5488   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5489   test involves parallel copies of the block off-diagonal parts of the matrix.
5490 
5491 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5492 @*/
5493 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5494 {
5495   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5496 
5497   PetscFunctionBegin;
5498   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5499   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5500   PetscAssertPointer(flg, 4);
5501   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5502   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5503   *flg = PETSC_FALSE;
5504   if (f && g) {
5505     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5506     PetscCall((*f)(A, B, tol, flg));
5507   } else {
5508     MatType mattype;
5509 
5510     PetscCall(MatGetType(f ? B : A, &mattype));
5511     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5512   }
5513   PetscFunctionReturn(PETSC_SUCCESS);
5514 }
5515 
5516 /*@
5517   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5518 
5519   Collective
5520 
5521   Input Parameters:
5522 + mat   - the matrix to transpose and complex conjugate
5523 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5524 
5525   Output Parameter:
5526 . B - the Hermitian transpose
5527 
5528   Level: intermediate
5529 
5530 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5531 @*/
5532 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5533 {
5534   PetscFunctionBegin;
5535   PetscCall(MatTranspose(mat, reuse, B));
5536 #if defined(PETSC_USE_COMPLEX)
5537   PetscCall(MatConjugate(*B));
5538 #endif
5539   PetscFunctionReturn(PETSC_SUCCESS);
5540 }
5541 
5542 /*@
5543   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5544 
5545   Collective
5546 
5547   Input Parameters:
5548 + A   - the matrix to test
5549 . B   - the matrix to test against, this can equal the first parameter
5550 - tol - tolerance, differences between entries smaller than this are counted as zero
5551 
5552   Output Parameter:
5553 . flg - the result
5554 
5555   Level: intermediate
5556 
5557   Notes:
5558   Only available for `MATAIJ` matrices.
5559 
5560   The sequential algorithm
5561   has a running time of the order of the number of nonzeros; the parallel
5562   test involves parallel copies of the block off-diagonal parts of the matrix.
5563 
5564 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5565 @*/
5566 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5567 {
5568   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5569 
5570   PetscFunctionBegin;
5571   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5572   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5573   PetscAssertPointer(flg, 4);
5574   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5575   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5576   if (f && g) {
5577     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5578     PetscCall((*f)(A, B, tol, flg));
5579   }
5580   PetscFunctionReturn(PETSC_SUCCESS);
5581 }
5582 
5583 /*@
5584   MatPermute - Creates a new matrix with rows and columns permuted from the
5585   original.
5586 
5587   Collective
5588 
5589   Input Parameters:
5590 + mat - the matrix to permute
5591 . row - row permutation, each processor supplies only the permutation for its rows
5592 - col - column permutation, each processor supplies only the permutation for its columns
5593 
5594   Output Parameter:
5595 . B - the permuted matrix
5596 
5597   Level: advanced
5598 
5599   Note:
5600   The index sets map from row/col of permuted matrix to row/col of original matrix.
5601   The index sets should be on the same communicator as mat and have the same local sizes.
5602 
5603   Developer Note:
5604   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5605   exploit the fact that row and col are permutations, consider implementing the
5606   more general `MatCreateSubMatrix()` instead.
5607 
5608 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5609 @*/
5610 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5611 {
5612   PetscFunctionBegin;
5613   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5614   PetscValidType(mat, 1);
5615   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5616   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5617   PetscAssertPointer(B, 4);
5618   PetscCheckSameComm(mat, 1, row, 2);
5619   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5620   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5621   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5622   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5623   MatCheckPreallocated(mat, 1);
5624 
5625   if (mat->ops->permute) {
5626     PetscUseTypeMethod(mat, permute, row, col, B);
5627     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5628   } else {
5629     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5630   }
5631   PetscFunctionReturn(PETSC_SUCCESS);
5632 }
5633 
5634 /*@
5635   MatEqual - Compares two matrices.
5636 
5637   Collective
5638 
5639   Input Parameters:
5640 + A - the first matrix
5641 - B - the second matrix
5642 
5643   Output Parameter:
5644 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5645 
5646   Level: intermediate
5647 
5648   Note:
5649   If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product
5650   using several randomly created vectors, see `MatMultEqual()`.
5651 
5652 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5653 @*/
5654 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5655 {
5656   PetscFunctionBegin;
5657   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5658   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5659   PetscValidType(A, 1);
5660   PetscValidType(B, 2);
5661   PetscAssertPointer(flg, 3);
5662   PetscCheckSameComm(A, 1, B, 2);
5663   MatCheckPreallocated(A, 1);
5664   MatCheckPreallocated(B, 2);
5665   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5666   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5667   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,
5668              B->cmap->N);
5669   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5670     PetscUseTypeMethod(A, equal, B, flg);
5671   } else {
5672     PetscCall(MatMultEqual(A, B, 10, flg));
5673   }
5674   PetscFunctionReturn(PETSC_SUCCESS);
5675 }
5676 
5677 /*@
5678   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5679   matrices that are stored as vectors.  Either of the two scaling
5680   matrices can be `NULL`.
5681 
5682   Collective
5683 
5684   Input Parameters:
5685 + mat - the matrix to be scaled
5686 . l   - the left scaling vector (or `NULL`)
5687 - r   - the right scaling vector (or `NULL`)
5688 
5689   Level: intermediate
5690 
5691   Note:
5692   `MatDiagonalScale()` computes $A = LAR$, where
5693   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5694   The L scales the rows of the matrix, the R scales the columns of the matrix.
5695 
5696 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5697 @*/
5698 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5699 {
5700   PetscFunctionBegin;
5701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5702   PetscValidType(mat, 1);
5703   if (l) {
5704     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5705     PetscCheckSameComm(mat, 1, l, 2);
5706   }
5707   if (r) {
5708     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5709     PetscCheckSameComm(mat, 1, r, 3);
5710   }
5711   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5712   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5713   MatCheckPreallocated(mat, 1);
5714   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5715 
5716   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5717   PetscUseTypeMethod(mat, diagonalscale, l, r);
5718   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5719   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5720   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5721   PetscFunctionReturn(PETSC_SUCCESS);
5722 }
5723 
5724 /*@
5725   MatScale - Scales all elements of a matrix by a given number.
5726 
5727   Logically Collective
5728 
5729   Input Parameters:
5730 + mat - the matrix to be scaled
5731 - a   - the scaling value
5732 
5733   Level: intermediate
5734 
5735 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5736 @*/
5737 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5738 {
5739   PetscFunctionBegin;
5740   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5741   PetscValidType(mat, 1);
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   PetscValidLogicalCollectiveScalar(mat, a, 2);
5745   MatCheckPreallocated(mat, 1);
5746 
5747   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5748   if (a != (PetscScalar)1.0) {
5749     PetscUseTypeMethod(mat, scale, a);
5750     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5751   }
5752   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5753   PetscFunctionReturn(PETSC_SUCCESS);
5754 }
5755 
5756 /*@
5757   MatNorm - Calculates various norms of a matrix.
5758 
5759   Collective
5760 
5761   Input Parameters:
5762 + mat  - the matrix
5763 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5764 
5765   Output Parameter:
5766 . nrm - the resulting norm
5767 
5768   Level: intermediate
5769 
5770 .seealso: [](ch_matrices), `Mat`
5771 @*/
5772 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5773 {
5774   PetscFunctionBegin;
5775   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5776   PetscValidType(mat, 1);
5777   PetscAssertPointer(nrm, 3);
5778 
5779   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5780   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5781   MatCheckPreallocated(mat, 1);
5782 
5783   PetscUseTypeMethod(mat, norm, type, nrm);
5784   PetscFunctionReturn(PETSC_SUCCESS);
5785 }
5786 
5787 /*
5788      This variable is used to prevent counting of MatAssemblyBegin() that
5789    are called from within a MatAssemblyEnd().
5790 */
5791 static PetscInt MatAssemblyEnd_InUse = 0;
5792 /*@
5793   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5794   be called after completing all calls to `MatSetValues()`.
5795 
5796   Collective
5797 
5798   Input Parameters:
5799 + mat  - the matrix
5800 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5801 
5802   Level: beginner
5803 
5804   Notes:
5805   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5806   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5807 
5808   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5809   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5810   using the matrix.
5811 
5812   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5813   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
5814   a global collective operation requiring all processes that share the matrix.
5815 
5816   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5817   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5818   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5819 
5820 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5821 @*/
5822 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5823 {
5824   PetscFunctionBegin;
5825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5826   PetscValidType(mat, 1);
5827   MatCheckPreallocated(mat, 1);
5828   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5829   if (mat->assembled) {
5830     mat->was_assembled = PETSC_TRUE;
5831     mat->assembled     = PETSC_FALSE;
5832   }
5833 
5834   if (!MatAssemblyEnd_InUse) {
5835     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5836     PetscTryTypeMethod(mat, assemblybegin, type);
5837     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5838   } else PetscTryTypeMethod(mat, assemblybegin, type);
5839   PetscFunctionReturn(PETSC_SUCCESS);
5840 }
5841 
5842 /*@
5843   MatAssembled - Indicates if a matrix has been assembled and is ready for
5844   use; for example, in matrix-vector product.
5845 
5846   Not Collective
5847 
5848   Input Parameter:
5849 . mat - the matrix
5850 
5851   Output Parameter:
5852 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5853 
5854   Level: advanced
5855 
5856 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5857 @*/
5858 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5859 {
5860   PetscFunctionBegin;
5861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5862   PetscAssertPointer(assembled, 2);
5863   *assembled = mat->assembled;
5864   PetscFunctionReturn(PETSC_SUCCESS);
5865 }
5866 
5867 /*@
5868   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5869   be called after `MatAssemblyBegin()`.
5870 
5871   Collective
5872 
5873   Input Parameters:
5874 + mat  - the matrix
5875 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5876 
5877   Options Database Keys:
5878 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5879 . -mat_view ::ascii_info_detail      - Prints more detailed info
5880 . -mat_view                          - Prints matrix in ASCII format
5881 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5882 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5883 . -display <name>                    - Sets display name (default is host)
5884 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5885 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5886 . -viewer_socket_machine <machine>   - Machine to use for socket
5887 . -viewer_socket_port <port>         - Port number to use for socket
5888 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5889 
5890   Level: beginner
5891 
5892 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5893 @*/
5894 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5895 {
5896   static PetscInt inassm = 0;
5897   PetscBool       flg    = PETSC_FALSE;
5898 
5899   PetscFunctionBegin;
5900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5901   PetscValidType(mat, 1);
5902 
5903   inassm++;
5904   MatAssemblyEnd_InUse++;
5905   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5906     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5907     PetscTryTypeMethod(mat, assemblyend, type);
5908     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5909   } else PetscTryTypeMethod(mat, assemblyend, type);
5910 
5911   /* Flush assembly is not a true assembly */
5912   if (type != MAT_FLUSH_ASSEMBLY) {
5913     if (mat->num_ass) {
5914       if (!mat->symmetry_eternal) {
5915         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5916         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5917       }
5918       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5919       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5920     }
5921     mat->num_ass++;
5922     mat->assembled        = PETSC_TRUE;
5923     mat->ass_nonzerostate = mat->nonzerostate;
5924   }
5925 
5926   mat->insertmode = NOT_SET_VALUES;
5927   MatAssemblyEnd_InUse--;
5928   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5929   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5930     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5931 
5932     if (mat->checksymmetryonassembly) {
5933       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5934       if (flg) {
5935         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5936       } else {
5937         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5938       }
5939     }
5940     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5941   }
5942   inassm--;
5943   PetscFunctionReturn(PETSC_SUCCESS);
5944 }
5945 
5946 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5947 /*@
5948   MatSetOption - Sets a parameter option for a matrix. Some options
5949   may be specific to certain storage formats.  Some options
5950   determine how values will be inserted (or added). Sorted,
5951   row-oriented input will generally assemble the fastest. The default
5952   is row-oriented.
5953 
5954   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5955 
5956   Input Parameters:
5957 + mat - the matrix
5958 . op  - the option, one of those listed below (and possibly others),
5959 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5960 
5961   Options Describing Matrix Structure:
5962 + `MAT_SPD`                         - symmetric positive definite
5963 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5964 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5965 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5966 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5967 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5968 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5969 
5970    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5971    do not need to be computed (usually at a high cost)
5972 
5973    Options For Use with `MatSetValues()`:
5974    Insert a logically dense subblock, which can be
5975 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5976 
5977    These options reflect the data you pass in with `MatSetValues()`; it has
5978    nothing to do with how the data is stored internally in the matrix
5979    data structure.
5980 
5981    When (re)assembling a matrix, we can restrict the input for
5982    efficiency/debugging purposes.  These options include
5983 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5984 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5985 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5986 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5987 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5988 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5989         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5990         performance for very large process counts.
5991 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5992         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5993         functions, instead sending only neighbor messages.
5994 
5995   Level: intermediate
5996 
5997   Notes:
5998   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5999 
6000   Some options are relevant only for particular matrix types and
6001   are thus ignored by others.  Other options are not supported by
6002   certain matrix types and will generate an error message if set.
6003 
6004   If using Fortran to compute a matrix, one may need to
6005   use the column-oriented option (or convert to the row-oriented
6006   format).
6007 
6008   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
6009   that would generate a new entry in the nonzero structure is instead
6010   ignored.  Thus, if memory has not already been allocated for this particular
6011   data, then the insertion is ignored. For dense matrices, in which
6012   the entire array is allocated, no entries are ever ignored.
6013   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6014 
6015   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6016   that would generate a new entry in the nonzero structure instead produces
6017   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
6018 
6019   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6020   that would generate a new entry that has not been preallocated will
6021   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6022   only.) This is a useful flag when debugging matrix memory preallocation.
6023   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6024 
6025   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6026   other processors should be dropped, rather than stashed.
6027   This is useful if you know that the "owning" processor is also
6028   always generating the correct matrix entries, so that PETSc need
6029   not transfer duplicate entries generated on another processor.
6030 
6031   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6032   searches during matrix assembly. When this flag is set, the hash table
6033   is created during the first matrix assembly. This hash table is
6034   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6035   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6036   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6037   supported by `MATMPIBAIJ` format only.
6038 
6039   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6040   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6041 
6042   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6043   a zero location in the matrix
6044 
6045   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6046 
6047   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6048   zero row routines and thus improves performance for very large process counts.
6049 
6050   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6051   part of the matrix (since they should match the upper triangular part).
6052 
6053   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6054   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6055   with finite difference schemes with non-periodic boundary conditions.
6056 
6057   Developer Note:
6058   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6059   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6060   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6061   not changed.
6062 
6063 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6064 @*/
6065 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6066 {
6067   PetscFunctionBegin;
6068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6069   if (op > 0) {
6070     PetscValidLogicalCollectiveEnum(mat, op, 2);
6071     PetscValidLogicalCollectiveBool(mat, flg, 3);
6072   }
6073 
6074   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);
6075 
6076   switch (op) {
6077   case MAT_FORCE_DIAGONAL_ENTRIES:
6078     mat->force_diagonals = flg;
6079     PetscFunctionReturn(PETSC_SUCCESS);
6080   case MAT_NO_OFF_PROC_ENTRIES:
6081     mat->nooffprocentries = flg;
6082     PetscFunctionReturn(PETSC_SUCCESS);
6083   case MAT_SUBSET_OFF_PROC_ENTRIES:
6084     mat->assembly_subset = flg;
6085     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6086 #if !defined(PETSC_HAVE_MPIUNI)
6087       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6088 #endif
6089       mat->stash.first_assembly_done = PETSC_FALSE;
6090     }
6091     PetscFunctionReturn(PETSC_SUCCESS);
6092   case MAT_NO_OFF_PROC_ZERO_ROWS:
6093     mat->nooffproczerorows = flg;
6094     PetscFunctionReturn(PETSC_SUCCESS);
6095   case MAT_SPD:
6096     if (flg) {
6097       mat->spd                    = PETSC_BOOL3_TRUE;
6098       mat->symmetric              = PETSC_BOOL3_TRUE;
6099       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6100     } else {
6101       mat->spd = PETSC_BOOL3_FALSE;
6102     }
6103     break;
6104   case MAT_SYMMETRIC:
6105     mat->symmetric = PetscBoolToBool3(flg);
6106     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6107 #if !defined(PETSC_USE_COMPLEX)
6108     mat->hermitian = PetscBoolToBool3(flg);
6109 #endif
6110     break;
6111   case MAT_HERMITIAN:
6112     mat->hermitian = PetscBoolToBool3(flg);
6113     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6114 #if !defined(PETSC_USE_COMPLEX)
6115     mat->symmetric = PetscBoolToBool3(flg);
6116 #endif
6117     break;
6118   case MAT_STRUCTURALLY_SYMMETRIC:
6119     mat->structurally_symmetric = PetscBoolToBool3(flg);
6120     break;
6121   case MAT_SYMMETRY_ETERNAL:
6122     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");
6123     mat->symmetry_eternal = flg;
6124     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6125     break;
6126   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6127     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");
6128     mat->structural_symmetry_eternal = flg;
6129     break;
6130   case MAT_SPD_ETERNAL:
6131     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");
6132     mat->spd_eternal = flg;
6133     if (flg) {
6134       mat->structural_symmetry_eternal = PETSC_TRUE;
6135       mat->symmetry_eternal            = PETSC_TRUE;
6136     }
6137     break;
6138   case MAT_STRUCTURE_ONLY:
6139     mat->structure_only = flg;
6140     break;
6141   case MAT_SORTED_FULL:
6142     mat->sortedfull = flg;
6143     break;
6144   default:
6145     break;
6146   }
6147   PetscTryTypeMethod(mat, setoption, op, flg);
6148   PetscFunctionReturn(PETSC_SUCCESS);
6149 }
6150 
6151 /*@
6152   MatGetOption - Gets a parameter option that has been set for a matrix.
6153 
6154   Logically Collective
6155 
6156   Input Parameters:
6157 + mat - the matrix
6158 - op  - the option, this only responds to certain options, check the code for which ones
6159 
6160   Output Parameter:
6161 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6162 
6163   Level: intermediate
6164 
6165   Notes:
6166   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6167 
6168   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6169   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6170 
6171 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6172     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6173 @*/
6174 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6175 {
6176   PetscFunctionBegin;
6177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6178   PetscValidType(mat, 1);
6179 
6180   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);
6181   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()");
6182 
6183   switch (op) {
6184   case MAT_NO_OFF_PROC_ENTRIES:
6185     *flg = mat->nooffprocentries;
6186     break;
6187   case MAT_NO_OFF_PROC_ZERO_ROWS:
6188     *flg = mat->nooffproczerorows;
6189     break;
6190   case MAT_SYMMETRIC:
6191     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6192     break;
6193   case MAT_HERMITIAN:
6194     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6195     break;
6196   case MAT_STRUCTURALLY_SYMMETRIC:
6197     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6198     break;
6199   case MAT_SPD:
6200     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6201     break;
6202   case MAT_SYMMETRY_ETERNAL:
6203     *flg = mat->symmetry_eternal;
6204     break;
6205   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6206     *flg = mat->symmetry_eternal;
6207     break;
6208   default:
6209     break;
6210   }
6211   PetscFunctionReturn(PETSC_SUCCESS);
6212 }
6213 
6214 /*@
6215   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6216   this routine retains the old nonzero structure.
6217 
6218   Logically Collective
6219 
6220   Input Parameter:
6221 . mat - the matrix
6222 
6223   Level: intermediate
6224 
6225   Note:
6226   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.
6227   See the Performance chapter of the users manual for information on preallocating matrices.
6228 
6229 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6230 @*/
6231 PetscErrorCode MatZeroEntries(Mat mat)
6232 {
6233   PetscFunctionBegin;
6234   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6235   PetscValidType(mat, 1);
6236   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6237   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");
6238   MatCheckPreallocated(mat, 1);
6239 
6240   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6241   PetscUseTypeMethod(mat, zeroentries);
6242   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6243   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6244   PetscFunctionReturn(PETSC_SUCCESS);
6245 }
6246 
6247 /*@
6248   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6249   of a set of rows and columns of a matrix.
6250 
6251   Collective
6252 
6253   Input Parameters:
6254 + mat     - the matrix
6255 . numRows - the number of rows/columns to zero
6256 . rows    - the global row indices
6257 . diag    - value put in the diagonal of the eliminated rows
6258 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6259 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6260 
6261   Level: intermediate
6262 
6263   Notes:
6264   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6265 
6266   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6267   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
6268 
6269   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6270   Krylov method to take advantage of the known solution on the zeroed rows.
6271 
6272   For the parallel case, all processes that share the matrix (i.e.,
6273   those in the communicator used for matrix creation) MUST call this
6274   routine, regardless of whether any rows being zeroed are owned by
6275   them.
6276 
6277   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6278   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
6279   missing.
6280 
6281   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6282   list only rows local to itself).
6283 
6284   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6285 
6286 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6287           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6288 @*/
6289 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6290 {
6291   PetscFunctionBegin;
6292   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6293   PetscValidType(mat, 1);
6294   if (numRows) PetscAssertPointer(rows, 3);
6295   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6296   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6297   MatCheckPreallocated(mat, 1);
6298 
6299   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6300   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6301   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6302   PetscFunctionReturn(PETSC_SUCCESS);
6303 }
6304 
6305 /*@
6306   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6307   of a set of rows and columns of a matrix.
6308 
6309   Collective
6310 
6311   Input Parameters:
6312 + mat  - the matrix
6313 . is   - the rows to zero
6314 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6315 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6316 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6317 
6318   Level: intermediate
6319 
6320   Note:
6321   See `MatZeroRowsColumns()` for details on how this routine operates.
6322 
6323 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6324           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6325 @*/
6326 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6327 {
6328   PetscInt        numRows;
6329   const PetscInt *rows;
6330 
6331   PetscFunctionBegin;
6332   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6333   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6334   PetscValidType(mat, 1);
6335   PetscValidType(is, 2);
6336   PetscCall(ISGetLocalSize(is, &numRows));
6337   PetscCall(ISGetIndices(is, &rows));
6338   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6339   PetscCall(ISRestoreIndices(is, &rows));
6340   PetscFunctionReturn(PETSC_SUCCESS);
6341 }
6342 
6343 /*@
6344   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6345   of a set of rows of a matrix.
6346 
6347   Collective
6348 
6349   Input Parameters:
6350 + mat     - the matrix
6351 . numRows - the number of rows to zero
6352 . rows    - the global row indices
6353 . diag    - value put in the diagonal of the zeroed rows
6354 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6355 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6356 
6357   Level: intermediate
6358 
6359   Notes:
6360   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6361 
6362   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6363 
6364   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6365   Krylov method to take advantage of the known solution on the zeroed rows.
6366 
6367   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)
6368   from the matrix.
6369 
6370   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6371   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6372   formats this does not alter the nonzero structure.
6373 
6374   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6375   of the matrix is not changed the values are
6376   merely zeroed.
6377 
6378   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6379   formats can optionally remove the main diagonal entry from the
6380   nonzero structure as well, by passing 0.0 as the final argument).
6381 
6382   For the parallel case, all processes that share the matrix (i.e.,
6383   those in the communicator used for matrix creation) MUST call this
6384   routine, regardless of whether any rows being zeroed are owned by
6385   them.
6386 
6387   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6388   list only rows local to itself).
6389 
6390   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6391   owns that are to be zeroed. This saves a global synchronization in the implementation.
6392 
6393 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6394           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6395 @*/
6396 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6397 {
6398   PetscFunctionBegin;
6399   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6400   PetscValidType(mat, 1);
6401   if (numRows) PetscAssertPointer(rows, 3);
6402   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6403   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6404   MatCheckPreallocated(mat, 1);
6405 
6406   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6407   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6408   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6409   PetscFunctionReturn(PETSC_SUCCESS);
6410 }
6411 
6412 /*@
6413   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6414   of a set of rows of a matrix indicated by an `IS`
6415 
6416   Collective
6417 
6418   Input Parameters:
6419 + mat  - the matrix
6420 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6421 . diag - value put in all diagonals of eliminated rows
6422 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6423 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6424 
6425   Level: intermediate
6426 
6427   Note:
6428   See `MatZeroRows()` for details on how this routine operates.
6429 
6430 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6431           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6432 @*/
6433 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6434 {
6435   PetscInt        numRows = 0;
6436   const PetscInt *rows    = NULL;
6437 
6438   PetscFunctionBegin;
6439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6440   PetscValidType(mat, 1);
6441   if (is) {
6442     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6443     PetscCall(ISGetLocalSize(is, &numRows));
6444     PetscCall(ISGetIndices(is, &rows));
6445   }
6446   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6447   if (is) PetscCall(ISRestoreIndices(is, &rows));
6448   PetscFunctionReturn(PETSC_SUCCESS);
6449 }
6450 
6451 /*@
6452   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6453   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6454 
6455   Collective
6456 
6457   Input Parameters:
6458 + mat     - the matrix
6459 . numRows - the number of rows to remove
6460 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6461 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6462 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6463 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6464 
6465   Level: intermediate
6466 
6467   Notes:
6468   See `MatZeroRows()` for details on how this routine operates.
6469 
6470   The grid coordinates are across the entire grid, not just the local portion
6471 
6472   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6473   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6474   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6475   `DM_BOUNDARY_PERIODIC` boundary type.
6476 
6477   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
6478   a single value per point) you can skip filling those indices.
6479 
6480   Fortran Note:
6481   `idxm` and `idxn` should be declared as
6482 $     MatStencil idxm(4, m)
6483   and the values inserted using
6484 .vb
6485     idxm(MatStencil_i, 1) = i
6486     idxm(MatStencil_j, 1) = j
6487     idxm(MatStencil_k, 1) = k
6488     idxm(MatStencil_c, 1) = c
6489    etc
6490 .ve
6491 
6492 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6493           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6494 @*/
6495 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6496 {
6497   PetscInt  dim    = mat->stencil.dim;
6498   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6499   PetscInt *dims   = mat->stencil.dims + 1;
6500   PetscInt *starts = mat->stencil.starts;
6501   PetscInt *dxm    = (PetscInt *)rows;
6502   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6503 
6504   PetscFunctionBegin;
6505   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6506   PetscValidType(mat, 1);
6507   if (numRows) PetscAssertPointer(rows, 3);
6508 
6509   PetscCall(PetscMalloc1(numRows, &jdxm));
6510   for (i = 0; i < numRows; ++i) {
6511     /* Skip unused dimensions (they are ordered k, j, i, c) */
6512     for (j = 0; j < 3 - sdim; ++j) dxm++;
6513     /* Local index in X dir */
6514     tmp = *dxm++ - starts[0];
6515     /* Loop over remaining dimensions */
6516     for (j = 0; j < dim - 1; ++j) {
6517       /* If nonlocal, set index to be negative */
6518       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6519       /* Update local index */
6520       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6521     }
6522     /* Skip component slot if necessary */
6523     if (mat->stencil.noc) dxm++;
6524     /* Local row number */
6525     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6526   }
6527   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6528   PetscCall(PetscFree(jdxm));
6529   PetscFunctionReturn(PETSC_SUCCESS);
6530 }
6531 
6532 /*@
6533   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6534   of a set of rows and columns of a matrix.
6535 
6536   Collective
6537 
6538   Input Parameters:
6539 + mat     - the matrix
6540 . numRows - the number of rows/columns to remove
6541 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6542 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6543 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6544 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6545 
6546   Level: intermediate
6547 
6548   Notes:
6549   See `MatZeroRowsColumns()` for details on how this routine operates.
6550 
6551   The grid coordinates are across the entire grid, not just the local portion
6552 
6553   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6554   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6555   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6556   `DM_BOUNDARY_PERIODIC` boundary type.
6557 
6558   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
6559   a single value per point) you can skip filling those indices.
6560 
6561   Fortran Note:
6562   `idxm` and `idxn` should be declared as
6563 $     MatStencil idxm(4, m)
6564   and the values inserted using
6565 .vb
6566     idxm(MatStencil_i, 1) = i
6567     idxm(MatStencil_j, 1) = j
6568     idxm(MatStencil_k, 1) = k
6569     idxm(MatStencil_c, 1) = c
6570     etc
6571 .ve
6572 
6573 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6574           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6575 @*/
6576 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6577 {
6578   PetscInt  dim    = mat->stencil.dim;
6579   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6580   PetscInt *dims   = mat->stencil.dims + 1;
6581   PetscInt *starts = mat->stencil.starts;
6582   PetscInt *dxm    = (PetscInt *)rows;
6583   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6584 
6585   PetscFunctionBegin;
6586   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6587   PetscValidType(mat, 1);
6588   if (numRows) PetscAssertPointer(rows, 3);
6589 
6590   PetscCall(PetscMalloc1(numRows, &jdxm));
6591   for (i = 0; i < numRows; ++i) {
6592     /* Skip unused dimensions (they are ordered k, j, i, c) */
6593     for (j = 0; j < 3 - sdim; ++j) dxm++;
6594     /* Local index in X dir */
6595     tmp = *dxm++ - starts[0];
6596     /* Loop over remaining dimensions */
6597     for (j = 0; j < dim - 1; ++j) {
6598       /* If nonlocal, set index to be negative */
6599       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6600       /* Update local index */
6601       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6602     }
6603     /* Skip component slot if necessary */
6604     if (mat->stencil.noc) dxm++;
6605     /* Local row number */
6606     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6607   }
6608   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6609   PetscCall(PetscFree(jdxm));
6610   PetscFunctionReturn(PETSC_SUCCESS);
6611 }
6612 
6613 /*@
6614   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6615   of a set of rows of a matrix; using local numbering of rows.
6616 
6617   Collective
6618 
6619   Input Parameters:
6620 + mat     - the matrix
6621 . numRows - the number of rows to remove
6622 . rows    - the local row indices
6623 . diag    - value put in all diagonals of eliminated rows
6624 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6625 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6626 
6627   Level: intermediate
6628 
6629   Notes:
6630   Before calling `MatZeroRowsLocal()`, the user must first set the
6631   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6632 
6633   See `MatZeroRows()` for details on how this routine operates.
6634 
6635 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6636           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6637 @*/
6638 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6639 {
6640   PetscFunctionBegin;
6641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6642   PetscValidType(mat, 1);
6643   if (numRows) PetscAssertPointer(rows, 3);
6644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6645   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6646   MatCheckPreallocated(mat, 1);
6647 
6648   if (mat->ops->zerorowslocal) {
6649     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6650   } else {
6651     IS              is, newis;
6652     const PetscInt *newRows;
6653 
6654     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6655     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6656     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6657     PetscCall(ISGetIndices(newis, &newRows));
6658     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6659     PetscCall(ISRestoreIndices(newis, &newRows));
6660     PetscCall(ISDestroy(&newis));
6661     PetscCall(ISDestroy(&is));
6662   }
6663   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6664   PetscFunctionReturn(PETSC_SUCCESS);
6665 }
6666 
6667 /*@
6668   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6669   of a set of rows of a matrix; using local numbering of rows.
6670 
6671   Collective
6672 
6673   Input Parameters:
6674 + mat  - the matrix
6675 . is   - index set of rows to remove
6676 . diag - value put in all diagonals of eliminated rows
6677 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6678 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6679 
6680   Level: intermediate
6681 
6682   Notes:
6683   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6684   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6685 
6686   See `MatZeroRows()` for details on how this routine operates.
6687 
6688 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6689           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6690 @*/
6691 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6692 {
6693   PetscInt        numRows;
6694   const PetscInt *rows;
6695 
6696   PetscFunctionBegin;
6697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6698   PetscValidType(mat, 1);
6699   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6700   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6701   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6702   MatCheckPreallocated(mat, 1);
6703 
6704   PetscCall(ISGetLocalSize(is, &numRows));
6705   PetscCall(ISGetIndices(is, &rows));
6706   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6707   PetscCall(ISRestoreIndices(is, &rows));
6708   PetscFunctionReturn(PETSC_SUCCESS);
6709 }
6710 
6711 /*@
6712   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6713   of a set of rows and columns of a matrix; using local numbering of rows.
6714 
6715   Collective
6716 
6717   Input Parameters:
6718 + mat     - the matrix
6719 . numRows - the number of rows to remove
6720 . rows    - the global row indices
6721 . diag    - value put in all diagonals of eliminated rows
6722 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6723 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6724 
6725   Level: intermediate
6726 
6727   Notes:
6728   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6729   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6730 
6731   See `MatZeroRowsColumns()` for details on how this routine operates.
6732 
6733 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6734           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6735 @*/
6736 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6737 {
6738   IS              is, newis;
6739   const PetscInt *newRows;
6740 
6741   PetscFunctionBegin;
6742   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6743   PetscValidType(mat, 1);
6744   if (numRows) PetscAssertPointer(rows, 3);
6745   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6746   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6747   MatCheckPreallocated(mat, 1);
6748 
6749   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6750   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6751   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6752   PetscCall(ISGetIndices(newis, &newRows));
6753   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6754   PetscCall(ISRestoreIndices(newis, &newRows));
6755   PetscCall(ISDestroy(&newis));
6756   PetscCall(ISDestroy(&is));
6757   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6758   PetscFunctionReturn(PETSC_SUCCESS);
6759 }
6760 
6761 /*@
6762   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6763   of a set of rows and columns of a matrix; using local numbering of rows.
6764 
6765   Collective
6766 
6767   Input Parameters:
6768 + mat  - the matrix
6769 . is   - index set of rows to remove
6770 . diag - value put in all diagonals of eliminated rows
6771 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6772 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6773 
6774   Level: intermediate
6775 
6776   Notes:
6777   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6778   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6779 
6780   See `MatZeroRowsColumns()` for details on how this routine operates.
6781 
6782 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6783           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6784 @*/
6785 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6786 {
6787   PetscInt        numRows;
6788   const PetscInt *rows;
6789 
6790   PetscFunctionBegin;
6791   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6792   PetscValidType(mat, 1);
6793   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6794   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6795   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6796   MatCheckPreallocated(mat, 1);
6797 
6798   PetscCall(ISGetLocalSize(is, &numRows));
6799   PetscCall(ISGetIndices(is, &rows));
6800   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6801   PetscCall(ISRestoreIndices(is, &rows));
6802   PetscFunctionReturn(PETSC_SUCCESS);
6803 }
6804 
6805 /*@
6806   MatGetSize - Returns the numbers of rows and columns in a matrix.
6807 
6808   Not Collective
6809 
6810   Input Parameter:
6811 . mat - the matrix
6812 
6813   Output Parameters:
6814 + m - the number of global rows
6815 - n - the number of global columns
6816 
6817   Level: beginner
6818 
6819   Note:
6820   Both output parameters can be `NULL` on input.
6821 
6822 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6823 @*/
6824 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6825 {
6826   PetscFunctionBegin;
6827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6828   if (m) *m = mat->rmap->N;
6829   if (n) *n = mat->cmap->N;
6830   PetscFunctionReturn(PETSC_SUCCESS);
6831 }
6832 
6833 /*@
6834   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6835   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6836 
6837   Not Collective
6838 
6839   Input Parameter:
6840 . mat - the matrix
6841 
6842   Output Parameters:
6843 + m - the number of local rows, use `NULL` to not obtain this value
6844 - n - the number of local columns, use `NULL` to not obtain this value
6845 
6846   Level: beginner
6847 
6848 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6849 @*/
6850 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6851 {
6852   PetscFunctionBegin;
6853   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6854   if (m) PetscAssertPointer(m, 2);
6855   if (n) PetscAssertPointer(n, 3);
6856   if (m) *m = mat->rmap->n;
6857   if (n) *n = mat->cmap->n;
6858   PetscFunctionReturn(PETSC_SUCCESS);
6859 }
6860 
6861 /*@
6862   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6863   vector one multiplies this matrix by that are owned by this processor.
6864 
6865   Not Collective, unless matrix has not been allocated, then collective
6866 
6867   Input Parameter:
6868 . mat - the matrix
6869 
6870   Output Parameters:
6871 + m - the global index of the first local column, use `NULL` to not obtain this value
6872 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6873 
6874   Level: developer
6875 
6876   Notes:
6877   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6878 
6879   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6880   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6881 
6882   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6883   the local values in the matrix.
6884 
6885   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6886   Layouts](sec_matlayout) for details on matrix layouts.
6887 
6888 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6889           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6890 @*/
6891 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6892 {
6893   PetscFunctionBegin;
6894   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6895   PetscValidType(mat, 1);
6896   if (m) PetscAssertPointer(m, 2);
6897   if (n) PetscAssertPointer(n, 3);
6898   MatCheckPreallocated(mat, 1);
6899   if (m) *m = mat->cmap->rstart;
6900   if (n) *n = mat->cmap->rend;
6901   PetscFunctionReturn(PETSC_SUCCESS);
6902 }
6903 
6904 /*@
6905   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6906   this MPI process.
6907 
6908   Not Collective
6909 
6910   Input Parameter:
6911 . mat - the matrix
6912 
6913   Output Parameters:
6914 + m - the global index of the first local row, use `NULL` to not obtain this value
6915 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6916 
6917   Level: beginner
6918 
6919   Notes:
6920   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6921 
6922   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6923   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6924 
6925   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6926   the local values in the matrix.
6927 
6928   The high argument is one more than the last element stored locally.
6929 
6930   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6931   would contain the result of a matrix vector product with this matrix. See [Matrix
6932   Layouts](sec_matlayout) for details on matrix layouts.
6933 
6934 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6935           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6936 @*/
6937 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6938 {
6939   PetscFunctionBegin;
6940   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6941   PetscValidType(mat, 1);
6942   if (m) PetscAssertPointer(m, 2);
6943   if (n) PetscAssertPointer(n, 3);
6944   MatCheckPreallocated(mat, 1);
6945   if (m) *m = mat->rmap->rstart;
6946   if (n) *n = mat->rmap->rend;
6947   PetscFunctionReturn(PETSC_SUCCESS);
6948 }
6949 
6950 /*@C
6951   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6952   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6953 
6954   Not Collective, unless matrix has not been allocated
6955 
6956   Input Parameter:
6957 . mat - the matrix
6958 
6959   Output Parameter:
6960 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6961            where `size` is the number of MPI processes used by `mat`
6962 
6963   Level: beginner
6964 
6965   Notes:
6966   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6967 
6968   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6969   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6970 
6971   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6972   the local values in the matrix.
6973 
6974   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6975   would contain the result of a matrix vector product with this matrix. See [Matrix
6976   Layouts](sec_matlayout) for details on matrix layouts.
6977 
6978 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6979           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6980           `DMDAGetGhostCorners()`, `DM`
6981 @*/
6982 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6983 {
6984   PetscFunctionBegin;
6985   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6986   PetscValidType(mat, 1);
6987   MatCheckPreallocated(mat, 1);
6988   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6989   PetscFunctionReturn(PETSC_SUCCESS);
6990 }
6991 
6992 /*@C
6993   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6994   vector one multiplies this vector by that are owned by each processor.
6995 
6996   Not Collective, unless matrix has not been allocated
6997 
6998   Input Parameter:
6999 . mat - the matrix
7000 
7001   Output Parameter:
7002 . ranges - start of each processors portion plus one more than the total length at the end
7003 
7004   Level: beginner
7005 
7006   Notes:
7007   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
7008 
7009   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7010   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7011 
7012   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7013   the local values in the matrix.
7014 
7015   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7016   Layouts](sec_matlayout) for details on matrix layouts.
7017 
7018 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7019           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7020           `DMDAGetGhostCorners()`, `DM`
7021 @*/
7022 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7023 {
7024   PetscFunctionBegin;
7025   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7026   PetscValidType(mat, 1);
7027   MatCheckPreallocated(mat, 1);
7028   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7029   PetscFunctionReturn(PETSC_SUCCESS);
7030 }
7031 
7032 /*@
7033   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7034 
7035   Not Collective
7036 
7037   Input Parameter:
7038 . A - matrix
7039 
7040   Output Parameters:
7041 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7042 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7043 
7044   Level: intermediate
7045 
7046   Note:
7047   You should call `ISDestroy()` on the returned `IS`
7048 
7049   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7050   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7051   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7052   details on matrix layouts.
7053 
7054 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7055 @*/
7056 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7057 {
7058   PetscErrorCode (*f)(Mat, IS *, IS *);
7059 
7060   PetscFunctionBegin;
7061   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7062   PetscValidType(A, 1);
7063   MatCheckPreallocated(A, 1);
7064   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7065   if (f) {
7066     PetscCall((*f)(A, rows, cols));
7067   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7068     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7069     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7070   }
7071   PetscFunctionReturn(PETSC_SUCCESS);
7072 }
7073 
7074 /*@
7075   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7076   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7077   to complete the factorization.
7078 
7079   Collective
7080 
7081   Input Parameters:
7082 + fact - the factorized matrix obtained with `MatGetFactor()`
7083 . mat  - the matrix
7084 . row  - row permutation
7085 . col  - column permutation
7086 - info - structure containing
7087 .vb
7088       levels - number of levels of fill.
7089       expected fill - as ratio of original fill.
7090       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7091                 missing diagonal entries)
7092 .ve
7093 
7094   Level: developer
7095 
7096   Notes:
7097   See [Matrix Factorization](sec_matfactor) for additional information.
7098 
7099   Most users should employ the `KSP` interface for linear solvers
7100   instead of working directly with matrix algebra routines such as this.
7101   See, e.g., `KSPCreate()`.
7102 
7103   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7104 
7105   Developer Note:
7106   The Fortran interface is not autogenerated as the
7107   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7108 
7109 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7110           `MatGetOrdering()`, `MatFactorInfo`
7111 @*/
7112 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7113 {
7114   PetscFunctionBegin;
7115   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7116   PetscValidType(mat, 2);
7117   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7118   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7119   PetscAssertPointer(info, 5);
7120   PetscAssertPointer(fact, 1);
7121   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7122   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7123   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7124   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7125   MatCheckPreallocated(mat, 2);
7126 
7127   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7128   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7129   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7130   PetscFunctionReturn(PETSC_SUCCESS);
7131 }
7132 
7133 /*@
7134   MatICCFactorSymbolic - Performs symbolic incomplete
7135   Cholesky factorization for a symmetric matrix.  Use
7136   `MatCholeskyFactorNumeric()` to complete the factorization.
7137 
7138   Collective
7139 
7140   Input Parameters:
7141 + fact - the factorized matrix obtained with `MatGetFactor()`
7142 . mat  - the matrix to be factored
7143 . perm - row and column permutation
7144 - info - structure containing
7145 .vb
7146       levels - number of levels of fill.
7147       expected fill - as ratio of original fill.
7148 .ve
7149 
7150   Level: developer
7151 
7152   Notes:
7153   Most users should employ the `KSP` interface for linear solvers
7154   instead of working directly with matrix algebra routines such as this.
7155   See, e.g., `KSPCreate()`.
7156 
7157   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7158 
7159   Developer Note:
7160   The Fortran interface is not autogenerated as the
7161   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7162 
7163 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7164 @*/
7165 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7166 {
7167   PetscFunctionBegin;
7168   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7169   PetscValidType(mat, 2);
7170   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7171   PetscAssertPointer(info, 4);
7172   PetscAssertPointer(fact, 1);
7173   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7174   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7175   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7176   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7177   MatCheckPreallocated(mat, 2);
7178 
7179   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7180   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7181   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7182   PetscFunctionReturn(PETSC_SUCCESS);
7183 }
7184 
7185 /*@C
7186   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7187   points to an array of valid matrices, they may be reused to store the new
7188   submatrices.
7189 
7190   Collective
7191 
7192   Input Parameters:
7193 + mat   - the matrix
7194 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7195 . irow  - index set of rows to extract
7196 . icol  - index set of columns to extract
7197 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7198 
7199   Output Parameter:
7200 . submat - the array of submatrices
7201 
7202   Level: advanced
7203 
7204   Notes:
7205   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7206   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7207   to extract a parallel submatrix.
7208 
7209   Some matrix types place restrictions on the row and column
7210   indices, such as that they be sorted or that they be equal to each other.
7211 
7212   The index sets may not have duplicate entries.
7213 
7214   When extracting submatrices from a parallel matrix, each processor can
7215   form a different submatrix by setting the rows and columns of its
7216   individual index sets according to the local submatrix desired.
7217 
7218   When finished using the submatrices, the user should destroy
7219   them with `MatDestroySubMatrices()`.
7220 
7221   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7222   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7223 
7224   This routine creates the matrices in submat; you should NOT create them before
7225   calling it. It also allocates the array of matrix pointers submat.
7226 
7227   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7228   request one row/column in a block, they must request all rows/columns that are in
7229   that block. For example, if the block size is 2 you cannot request just row 0 and
7230   column 0.
7231 
7232   Fortran Note:
7233 .vb
7234   Mat, pointer :: submat(:)
7235 .ve
7236 
7237 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7238 @*/
7239 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7240 {
7241   PetscInt  i;
7242   PetscBool eq;
7243 
7244   PetscFunctionBegin;
7245   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7246   PetscValidType(mat, 1);
7247   if (n) {
7248     PetscAssertPointer(irow, 3);
7249     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7250     PetscAssertPointer(icol, 4);
7251     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7252   }
7253   PetscAssertPointer(submat, 6);
7254   if (n && scall == MAT_REUSE_MATRIX) {
7255     PetscAssertPointer(*submat, 6);
7256     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7257   }
7258   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7259   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7260   MatCheckPreallocated(mat, 1);
7261   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7262   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7263   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7264   for (i = 0; i < n; i++) {
7265     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7266     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7267     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7268 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7269     if (mat->boundtocpu && mat->bindingpropagates) {
7270       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7271       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7272     }
7273 #endif
7274   }
7275   PetscFunctionReturn(PETSC_SUCCESS);
7276 }
7277 
7278 /*@C
7279   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms).
7280 
7281   Collective
7282 
7283   Input Parameters:
7284 + mat   - the matrix
7285 . n     - the number of submatrixes to be extracted
7286 . irow  - index set of rows to extract
7287 . icol  - index set of columns to extract
7288 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7289 
7290   Output Parameter:
7291 . submat - the array of submatrices
7292 
7293   Level: advanced
7294 
7295   Note:
7296   This is used by `PCGASM`
7297 
7298 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7299 @*/
7300 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7301 {
7302   PetscInt  i;
7303   PetscBool eq;
7304 
7305   PetscFunctionBegin;
7306   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7307   PetscValidType(mat, 1);
7308   if (n) {
7309     PetscAssertPointer(irow, 3);
7310     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7311     PetscAssertPointer(icol, 4);
7312     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7313   }
7314   PetscAssertPointer(submat, 6);
7315   if (n && scall == MAT_REUSE_MATRIX) {
7316     PetscAssertPointer(*submat, 6);
7317     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7318   }
7319   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7320   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7321   MatCheckPreallocated(mat, 1);
7322 
7323   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7324   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7325   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7326   for (i = 0; i < n; i++) {
7327     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7328     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7329   }
7330   PetscFunctionReturn(PETSC_SUCCESS);
7331 }
7332 
7333 /*@C
7334   MatDestroyMatrices - Destroys an array of matrices
7335 
7336   Collective
7337 
7338   Input Parameters:
7339 + n   - the number of local matrices
7340 - mat - the matrices (this is a pointer to the array of matrices)
7341 
7342   Level: advanced
7343 
7344   Notes:
7345   Frees not only the matrices, but also the array that contains the matrices
7346 
7347   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7348 
7349   Fortran Note:
7350   Does not free the `mat` array.
7351 
7352 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7353 @*/
7354 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7355 {
7356   PetscInt i;
7357 
7358   PetscFunctionBegin;
7359   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7360   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7361   PetscAssertPointer(mat, 2);
7362 
7363   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7364 
7365   /* memory is allocated even if n = 0 */
7366   PetscCall(PetscFree(*mat));
7367   PetscFunctionReturn(PETSC_SUCCESS);
7368 }
7369 
7370 /*@C
7371   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7372 
7373   Collective
7374 
7375   Input Parameters:
7376 + n   - the number of local matrices
7377 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`)
7378 
7379   Level: advanced
7380 
7381   Note:
7382   Frees not only the matrices, but also the array that contains the matrices
7383 
7384 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7385 @*/
7386 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7387 {
7388   Mat mat0;
7389 
7390   PetscFunctionBegin;
7391   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7392   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7393   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7394   PetscAssertPointer(mat, 2);
7395 
7396   mat0 = (*mat)[0];
7397   if (mat0 && mat0->ops->destroysubmatrices) {
7398     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7399   } else {
7400     PetscCall(MatDestroyMatrices(n, mat));
7401   }
7402   PetscFunctionReturn(PETSC_SUCCESS);
7403 }
7404 
7405 /*@
7406   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7407 
7408   Collective
7409 
7410   Input Parameter:
7411 . mat - the matrix
7412 
7413   Output Parameter:
7414 . matstruct - the sequential matrix with the nonzero structure of `mat`
7415 
7416   Level: developer
7417 
7418 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7419 @*/
7420 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7421 {
7422   PetscFunctionBegin;
7423   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7424   PetscAssertPointer(matstruct, 2);
7425 
7426   PetscValidType(mat, 1);
7427   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7428   MatCheckPreallocated(mat, 1);
7429 
7430   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7431   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7432   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7433   PetscFunctionReturn(PETSC_SUCCESS);
7434 }
7435 
7436 /*@C
7437   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7438 
7439   Collective
7440 
7441   Input Parameter:
7442 . mat - the matrix
7443 
7444   Level: advanced
7445 
7446   Note:
7447   This is not needed, one can just call `MatDestroy()`
7448 
7449 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7450 @*/
7451 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7452 {
7453   PetscFunctionBegin;
7454   PetscAssertPointer(mat, 1);
7455   PetscCall(MatDestroy(mat));
7456   PetscFunctionReturn(PETSC_SUCCESS);
7457 }
7458 
7459 /*@
7460   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7461   replaces the index sets by larger ones that represent submatrices with
7462   additional overlap.
7463 
7464   Collective
7465 
7466   Input Parameters:
7467 + mat - the matrix
7468 . n   - the number of index sets
7469 . is  - the array of index sets (these index sets will changed during the call)
7470 - ov  - the additional overlap requested
7471 
7472   Options Database Key:
7473 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7474 
7475   Level: developer
7476 
7477   Note:
7478   The computed overlap preserves the matrix block sizes when the blocks are square.
7479   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7480   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7481 
7482 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7483 @*/
7484 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7485 {
7486   PetscInt i, bs, cbs;
7487 
7488   PetscFunctionBegin;
7489   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7490   PetscValidType(mat, 1);
7491   PetscValidLogicalCollectiveInt(mat, n, 2);
7492   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7493   if (n) {
7494     PetscAssertPointer(is, 3);
7495     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7496   }
7497   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7498   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7499   MatCheckPreallocated(mat, 1);
7500 
7501   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7502   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7503   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7504   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7505   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7506   if (bs == cbs) {
7507     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7508   }
7509   PetscFunctionReturn(PETSC_SUCCESS);
7510 }
7511 
7512 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7513 
7514 /*@
7515   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7516   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7517   additional overlap.
7518 
7519   Collective
7520 
7521   Input Parameters:
7522 + mat - the matrix
7523 . n   - the number of index sets
7524 . is  - the array of index sets (these index sets will changed during the call)
7525 - ov  - the additional overlap requested
7526 
7527   `   Options Database Key:
7528 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7529 
7530   Level: developer
7531 
7532 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7533 @*/
7534 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7535 {
7536   PetscInt i;
7537 
7538   PetscFunctionBegin;
7539   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7540   PetscValidType(mat, 1);
7541   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7542   if (n) {
7543     PetscAssertPointer(is, 3);
7544     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7545   }
7546   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7547   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7548   MatCheckPreallocated(mat, 1);
7549   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7550   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7551   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7552   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7553   PetscFunctionReturn(PETSC_SUCCESS);
7554 }
7555 
7556 /*@
7557   MatGetBlockSize - Returns the matrix block size.
7558 
7559   Not Collective
7560 
7561   Input Parameter:
7562 . mat - the matrix
7563 
7564   Output Parameter:
7565 . bs - block size
7566 
7567   Level: intermediate
7568 
7569   Notes:
7570   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7571 
7572   If the block size has not been set yet this routine returns 1.
7573 
7574 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7575 @*/
7576 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7577 {
7578   PetscFunctionBegin;
7579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7580   PetscAssertPointer(bs, 2);
7581   *bs = PetscAbs(mat->rmap->bs);
7582   PetscFunctionReturn(PETSC_SUCCESS);
7583 }
7584 
7585 /*@
7586   MatGetBlockSizes - Returns the matrix block row and column sizes.
7587 
7588   Not Collective
7589 
7590   Input Parameter:
7591 . mat - the matrix
7592 
7593   Output Parameters:
7594 + rbs - row block size
7595 - cbs - column block size
7596 
7597   Level: intermediate
7598 
7599   Notes:
7600   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7601   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7602 
7603   If a block size has not been set yet this routine returns 1.
7604 
7605 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7606 @*/
7607 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7608 {
7609   PetscFunctionBegin;
7610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7611   if (rbs) PetscAssertPointer(rbs, 2);
7612   if (cbs) PetscAssertPointer(cbs, 3);
7613   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7614   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7615   PetscFunctionReturn(PETSC_SUCCESS);
7616 }
7617 
7618 /*@
7619   MatSetBlockSize - Sets the matrix block size.
7620 
7621   Logically Collective
7622 
7623   Input Parameters:
7624 + mat - the matrix
7625 - bs  - block size
7626 
7627   Level: intermediate
7628 
7629   Notes:
7630   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7631   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7632 
7633   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7634   is compatible with the matrix local sizes.
7635 
7636 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7637 @*/
7638 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7639 {
7640   PetscFunctionBegin;
7641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7642   PetscValidLogicalCollectiveInt(mat, bs, 2);
7643   PetscCall(MatSetBlockSizes(mat, bs, bs));
7644   PetscFunctionReturn(PETSC_SUCCESS);
7645 }
7646 
7647 typedef struct {
7648   PetscInt         n;
7649   IS              *is;
7650   Mat             *mat;
7651   PetscObjectState nonzerostate;
7652   Mat              C;
7653 } EnvelopeData;
7654 
7655 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7656 {
7657   EnvelopeData *edata = (EnvelopeData *)*ptr;
7658 
7659   PetscFunctionBegin;
7660   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7661   PetscCall(PetscFree(edata->is));
7662   PetscCall(PetscFree(edata));
7663   PetscFunctionReturn(PETSC_SUCCESS);
7664 }
7665 
7666 /*@
7667   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7668   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7669 
7670   Collective
7671 
7672   Input Parameter:
7673 . mat - the matrix
7674 
7675   Level: intermediate
7676 
7677   Notes:
7678   There can be zeros within the blocks
7679 
7680   The blocks can overlap between processes, including laying on more than two processes
7681 
7682 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7683 @*/
7684 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7685 {
7686   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7687   PetscInt          *diag, *odiag, sc;
7688   VecScatter         scatter;
7689   PetscScalar       *seqv;
7690   const PetscScalar *parv;
7691   const PetscInt    *ia, *ja;
7692   PetscBool          set, flag, done;
7693   Mat                AA = mat, A;
7694   MPI_Comm           comm;
7695   PetscMPIInt        rank, size, tag;
7696   MPI_Status         status;
7697   PetscContainer     container;
7698   EnvelopeData      *edata;
7699   Vec                seq, par;
7700   IS                 isglobal;
7701 
7702   PetscFunctionBegin;
7703   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7704   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7705   if (!set || !flag) {
7706     /* TODO: only needs nonzero structure of transpose */
7707     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7708     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7709   }
7710   PetscCall(MatAIJGetLocalMat(AA, &A));
7711   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7712   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7713 
7714   PetscCall(MatGetLocalSize(mat, &n, NULL));
7715   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7716   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7717   PetscCallMPI(MPI_Comm_size(comm, &size));
7718   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7719 
7720   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7721 
7722   if (rank > 0) {
7723     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7724     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7725   }
7726   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7727   for (i = 0; i < n; i++) {
7728     env = PetscMax(env, ja[ia[i + 1] - 1]);
7729     II  = rstart + i;
7730     if (env == II) {
7731       starts[lblocks]  = tbs;
7732       sizes[lblocks++] = 1 + II - tbs;
7733       tbs              = 1 + II;
7734     }
7735   }
7736   if (rank < size - 1) {
7737     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7738     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7739   }
7740 
7741   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7742   if (!set || !flag) PetscCall(MatDestroy(&AA));
7743   PetscCall(MatDestroy(&A));
7744 
7745   PetscCall(PetscNew(&edata));
7746   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7747   edata->n = lblocks;
7748   /* create IS needed for extracting blocks from the original matrix */
7749   PetscCall(PetscMalloc1(lblocks, &edata->is));
7750   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7751 
7752   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7753   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7754   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7755   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7756   PetscCall(MatSetType(edata->C, MATAIJ));
7757 
7758   /* Communicate the start and end of each row, from each block to the correct rank */
7759   /* TODO: Use PetscSF instead of VecScatter */
7760   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7761   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7762   PetscCall(VecGetArrayWrite(seq, &seqv));
7763   for (PetscInt i = 0; i < lblocks; i++) {
7764     for (PetscInt j = 0; j < sizes[i]; j++) {
7765       seqv[cnt]     = starts[i];
7766       seqv[cnt + 1] = starts[i] + sizes[i];
7767       cnt += 2;
7768     }
7769   }
7770   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7771   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7772   sc -= cnt;
7773   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7774   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7775   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7776   PetscCall(ISDestroy(&isglobal));
7777   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7778   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7779   PetscCall(VecScatterDestroy(&scatter));
7780   PetscCall(VecDestroy(&seq));
7781   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7782   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7783   PetscCall(VecGetArrayRead(par, &parv));
7784   cnt = 0;
7785   PetscCall(MatGetSize(mat, NULL, &n));
7786   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7787     PetscInt start, end, d = 0, od = 0;
7788 
7789     start = (PetscInt)PetscRealPart(parv[cnt]);
7790     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7791     cnt += 2;
7792 
7793     if (start < cstart) {
7794       od += cstart - start + n - cend;
7795       d += cend - cstart;
7796     } else if (start < cend) {
7797       od += n - cend;
7798       d += cend - start;
7799     } else od += n - start;
7800     if (end <= cstart) {
7801       od -= cstart - end + n - cend;
7802       d -= cend - cstart;
7803     } else if (end < cend) {
7804       od -= n - cend;
7805       d -= cend - end;
7806     } else od -= n - end;
7807 
7808     odiag[i] = od;
7809     diag[i]  = d;
7810   }
7811   PetscCall(VecRestoreArrayRead(par, &parv));
7812   PetscCall(VecDestroy(&par));
7813   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7814   PetscCall(PetscFree2(diag, odiag));
7815   PetscCall(PetscFree2(sizes, starts));
7816 
7817   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7818   PetscCall(PetscContainerSetPointer(container, edata));
7819   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7820   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7821   PetscCall(PetscObjectDereference((PetscObject)container));
7822   PetscFunctionReturn(PETSC_SUCCESS);
7823 }
7824 
7825 /*@
7826   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7827 
7828   Collective
7829 
7830   Input Parameters:
7831 + A     - the matrix
7832 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7833 
7834   Output Parameter:
7835 . C - matrix with inverted block diagonal of `A`
7836 
7837   Level: advanced
7838 
7839   Note:
7840   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7841 
7842 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7843 @*/
7844 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7845 {
7846   PetscContainer   container;
7847   EnvelopeData    *edata;
7848   PetscObjectState nonzerostate;
7849 
7850   PetscFunctionBegin;
7851   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7852   if (!container) {
7853     PetscCall(MatComputeVariableBlockEnvelope(A));
7854     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7855   }
7856   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7857   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7858   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7859   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7860 
7861   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7862   *C = edata->C;
7863 
7864   for (PetscInt i = 0; i < edata->n; i++) {
7865     Mat          D;
7866     PetscScalar *dvalues;
7867 
7868     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7869     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7870     PetscCall(MatSeqDenseInvert(D));
7871     PetscCall(MatDenseGetArray(D, &dvalues));
7872     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7873     PetscCall(MatDestroy(&D));
7874   }
7875   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7876   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7877   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7878   PetscFunctionReturn(PETSC_SUCCESS);
7879 }
7880 
7881 /*@
7882   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7883 
7884   Not Collective
7885 
7886   Input Parameters:
7887 + mat     - the matrix
7888 . nblocks - the number of blocks on this process, each block can only exist on a single process
7889 - bsizes  - the block sizes
7890 
7891   Level: intermediate
7892 
7893   Notes:
7894   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7895 
7896   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.
7897 
7898 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7899           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7900 @*/
7901 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7902 {
7903   PetscInt ncnt = 0, nlocal;
7904 
7905   PetscFunctionBegin;
7906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7907   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7908   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);
7909   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7910   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);
7911   PetscCall(PetscFree(mat->bsizes));
7912   mat->nblocks = nblocks;
7913   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7914   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7915   PetscFunctionReturn(PETSC_SUCCESS);
7916 }
7917 
7918 /*@C
7919   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7920 
7921   Not Collective; No Fortran Support
7922 
7923   Input Parameter:
7924 . mat - the matrix
7925 
7926   Output Parameters:
7927 + nblocks - the number of blocks on this process
7928 - bsizes  - the block sizes
7929 
7930   Level: intermediate
7931 
7932 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7933 @*/
7934 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7935 {
7936   PetscFunctionBegin;
7937   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7938   if (nblocks) *nblocks = mat->nblocks;
7939   if (bsizes) *bsizes = mat->bsizes;
7940   PetscFunctionReturn(PETSC_SUCCESS);
7941 }
7942 
7943 /*@
7944   MatSetBlockSizes - Sets the matrix block row and column sizes.
7945 
7946   Logically Collective
7947 
7948   Input Parameters:
7949 + mat - the matrix
7950 . rbs - row block size
7951 - cbs - column block size
7952 
7953   Level: intermediate
7954 
7955   Notes:
7956   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7957   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7958   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7959 
7960   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7961   are compatible with the matrix local sizes.
7962 
7963   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7964 
7965 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7966 @*/
7967 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7968 {
7969   PetscFunctionBegin;
7970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7971   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7972   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7973   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7974   if (mat->rmap->refcnt) {
7975     ISLocalToGlobalMapping l2g  = NULL;
7976     PetscLayout            nmap = NULL;
7977 
7978     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7979     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7980     PetscCall(PetscLayoutDestroy(&mat->rmap));
7981     mat->rmap          = nmap;
7982     mat->rmap->mapping = l2g;
7983   }
7984   if (mat->cmap->refcnt) {
7985     ISLocalToGlobalMapping l2g  = NULL;
7986     PetscLayout            nmap = NULL;
7987 
7988     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7989     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7990     PetscCall(PetscLayoutDestroy(&mat->cmap));
7991     mat->cmap          = nmap;
7992     mat->cmap->mapping = l2g;
7993   }
7994   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7995   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7996   PetscFunctionReturn(PETSC_SUCCESS);
7997 }
7998 
7999 /*@
8000   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
8001 
8002   Logically Collective
8003 
8004   Input Parameters:
8005 + mat     - the matrix
8006 . fromRow - matrix from which to copy row block size
8007 - fromCol - matrix from which to copy column block size (can be same as fromRow)
8008 
8009   Level: developer
8010 
8011 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
8012 @*/
8013 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8014 {
8015   PetscFunctionBegin;
8016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8017   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8018   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8019   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8020   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8021   PetscFunctionReturn(PETSC_SUCCESS);
8022 }
8023 
8024 /*@
8025   MatResidual - Default routine to calculate the residual r = b - Ax
8026 
8027   Collective
8028 
8029   Input Parameters:
8030 + mat - the matrix
8031 . b   - the right-hand-side
8032 - x   - the approximate solution
8033 
8034   Output Parameter:
8035 . r - location to store the residual
8036 
8037   Level: developer
8038 
8039 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8040 @*/
8041 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8042 {
8043   PetscFunctionBegin;
8044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8045   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8046   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8047   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8048   PetscValidType(mat, 1);
8049   MatCheckPreallocated(mat, 1);
8050   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8051   if (!mat->ops->residual) {
8052     PetscCall(MatMult(mat, x, r));
8053     PetscCall(VecAYPX(r, -1.0, b));
8054   } else {
8055     PetscUseTypeMethod(mat, residual, b, x, r);
8056   }
8057   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8058   PetscFunctionReturn(PETSC_SUCCESS);
8059 }
8060 
8061 /*@C
8062   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8063 
8064   Collective
8065 
8066   Input Parameters:
8067 + mat             - the matrix
8068 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8069 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8070 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8071                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8072                  always used.
8073 
8074   Output Parameters:
8075 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8076 . 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
8077 . ja   - the column indices, use `NULL` if not needed
8078 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8079            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8080 
8081   Level: developer
8082 
8083   Notes:
8084   You CANNOT change any of the ia[] or ja[] values.
8085 
8086   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8087 
8088   Fortran Notes:
8089   Use
8090 .vb
8091     PetscInt, pointer :: ia(:),ja(:)
8092     call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8093     ! Access the ith and jth entries via ia(i) and ja(j)
8094 .ve
8095 
8096 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8097 @*/
8098 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8099 {
8100   PetscFunctionBegin;
8101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8102   PetscValidType(mat, 1);
8103   if (n) PetscAssertPointer(n, 5);
8104   if (ia) PetscAssertPointer(ia, 6);
8105   if (ja) PetscAssertPointer(ja, 7);
8106   if (done) PetscAssertPointer(done, 8);
8107   MatCheckPreallocated(mat, 1);
8108   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8109   else {
8110     if (done) *done = PETSC_TRUE;
8111     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8112     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8113     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8114   }
8115   PetscFunctionReturn(PETSC_SUCCESS);
8116 }
8117 
8118 /*@C
8119   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8120 
8121   Collective
8122 
8123   Input Parameters:
8124 + mat             - the matrix
8125 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8126 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8127                 symmetrized
8128 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8129                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8130                  always used.
8131 . n               - number of columns in the (possibly compressed) matrix
8132 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8133 - ja              - the row indices
8134 
8135   Output Parameter:
8136 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8137 
8138   Level: developer
8139 
8140 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8141 @*/
8142 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8143 {
8144   PetscFunctionBegin;
8145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8146   PetscValidType(mat, 1);
8147   PetscAssertPointer(n, 5);
8148   if (ia) PetscAssertPointer(ia, 6);
8149   if (ja) PetscAssertPointer(ja, 7);
8150   PetscAssertPointer(done, 8);
8151   MatCheckPreallocated(mat, 1);
8152   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8153   else {
8154     *done = PETSC_TRUE;
8155     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8156   }
8157   PetscFunctionReturn(PETSC_SUCCESS);
8158 }
8159 
8160 /*@C
8161   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8162 
8163   Collective
8164 
8165   Input Parameters:
8166 + mat             - the matrix
8167 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8168 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8169 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8170                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8171                     always used.
8172 . n               - size of (possibly compressed) matrix
8173 . ia              - the row pointers
8174 - ja              - the column indices
8175 
8176   Output Parameter:
8177 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8178 
8179   Level: developer
8180 
8181   Note:
8182   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8183   us of the array after it has been restored. If you pass `NULL`, it will
8184   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8185 
8186 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8187 @*/
8188 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8189 {
8190   PetscFunctionBegin;
8191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8192   PetscValidType(mat, 1);
8193   if (ia) PetscAssertPointer(ia, 6);
8194   if (ja) PetscAssertPointer(ja, 7);
8195   if (done) PetscAssertPointer(done, 8);
8196   MatCheckPreallocated(mat, 1);
8197 
8198   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8199   else {
8200     if (done) *done = PETSC_TRUE;
8201     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8202     if (n) *n = 0;
8203     if (ia) *ia = NULL;
8204     if (ja) *ja = NULL;
8205   }
8206   PetscFunctionReturn(PETSC_SUCCESS);
8207 }
8208 
8209 /*@C
8210   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8211 
8212   Collective
8213 
8214   Input Parameters:
8215 + mat             - the matrix
8216 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8217 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8218 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8219                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8220                     always used.
8221 
8222   Output Parameters:
8223 + n    - size of (possibly compressed) matrix
8224 . ia   - the column pointers
8225 . ja   - the row indices
8226 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8227 
8228   Level: developer
8229 
8230 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8231 @*/
8232 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8233 {
8234   PetscFunctionBegin;
8235   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8236   PetscValidType(mat, 1);
8237   if (ia) PetscAssertPointer(ia, 6);
8238   if (ja) PetscAssertPointer(ja, 7);
8239   PetscAssertPointer(done, 8);
8240   MatCheckPreallocated(mat, 1);
8241 
8242   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8243   else {
8244     *done = PETSC_TRUE;
8245     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8246     if (n) *n = 0;
8247     if (ia) *ia = NULL;
8248     if (ja) *ja = NULL;
8249   }
8250   PetscFunctionReturn(PETSC_SUCCESS);
8251 }
8252 
8253 /*@
8254   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8255   `MatGetColumnIJ()`.
8256 
8257   Collective
8258 
8259   Input Parameters:
8260 + mat        - the matrix
8261 . ncolors    - maximum color value
8262 . n          - number of entries in colorarray
8263 - colorarray - array indicating color for each column
8264 
8265   Output Parameter:
8266 . iscoloring - coloring generated using colorarray information
8267 
8268   Level: developer
8269 
8270 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8271 @*/
8272 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8273 {
8274   PetscFunctionBegin;
8275   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8276   PetscValidType(mat, 1);
8277   PetscAssertPointer(colorarray, 4);
8278   PetscAssertPointer(iscoloring, 5);
8279   MatCheckPreallocated(mat, 1);
8280 
8281   if (!mat->ops->coloringpatch) {
8282     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8283   } else {
8284     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8285   }
8286   PetscFunctionReturn(PETSC_SUCCESS);
8287 }
8288 
8289 /*@
8290   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8291 
8292   Logically Collective
8293 
8294   Input Parameter:
8295 . mat - the factored matrix to be reset
8296 
8297   Level: developer
8298 
8299   Notes:
8300   This routine should be used only with factored matrices formed by in-place
8301   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8302   format).  This option can save memory, for example, when solving nonlinear
8303   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8304   ILU(0) preconditioner.
8305 
8306   One can specify in-place ILU(0) factorization by calling
8307 .vb
8308      PCType(pc,PCILU);
8309      PCFactorSeUseInPlace(pc);
8310 .ve
8311   or by using the options -pc_type ilu -pc_factor_in_place
8312 
8313   In-place factorization ILU(0) can also be used as a local
8314   solver for the blocks within the block Jacobi or additive Schwarz
8315   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8316   for details on setting local solver options.
8317 
8318   Most users should employ the `KSP` interface for linear solvers
8319   instead of working directly with matrix algebra routines such as this.
8320   See, e.g., `KSPCreate()`.
8321 
8322 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8323 @*/
8324 PetscErrorCode MatSetUnfactored(Mat mat)
8325 {
8326   PetscFunctionBegin;
8327   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8328   PetscValidType(mat, 1);
8329   MatCheckPreallocated(mat, 1);
8330   mat->factortype = MAT_FACTOR_NONE;
8331   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8332   PetscUseTypeMethod(mat, setunfactored);
8333   PetscFunctionReturn(PETSC_SUCCESS);
8334 }
8335 
8336 /*@
8337   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8338   as the original matrix.
8339 
8340   Collective
8341 
8342   Input Parameters:
8343 + mat   - the original matrix
8344 . isrow - parallel `IS` containing the rows this processor should obtain
8345 . 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.
8346 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8347 
8348   Output Parameter:
8349 . newmat - the new submatrix, of the same type as the original matrix
8350 
8351   Level: advanced
8352 
8353   Notes:
8354   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8355 
8356   Some matrix types place restrictions on the row and column indices, such
8357   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;
8358   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8359 
8360   The index sets may not have duplicate entries.
8361 
8362   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8363   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8364   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8365   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8366   you are finished using it.
8367 
8368   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8369   the input matrix.
8370 
8371   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8372 
8373   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8374   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8375 
8376   Example usage:
8377   Consider the following 8x8 matrix with 34 non-zero values, that is
8378   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8379   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8380   as follows
8381 .vb
8382             1  2  0  |  0  3  0  |  0  4
8383     Proc0   0  5  6  |  7  0  0  |  8  0
8384             9  0 10  | 11  0  0  | 12  0
8385     -------------------------------------
8386            13  0 14  | 15 16 17  |  0  0
8387     Proc1   0 18  0  | 19 20 21  |  0  0
8388             0  0  0  | 22 23  0  | 24  0
8389     -------------------------------------
8390     Proc2  25 26 27  |  0  0 28  | 29  0
8391            30  0  0  | 31 32 33  |  0 34
8392 .ve
8393 
8394   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8395 
8396 .vb
8397             2  0  |  0  3  0  |  0
8398     Proc0   5  6  |  7  0  0  |  8
8399     -------------------------------
8400     Proc1  18  0  | 19 20 21  |  0
8401     -------------------------------
8402     Proc2  26 27  |  0  0 28  | 29
8403             0  0  | 31 32 33  |  0
8404 .ve
8405 
8406 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8407 @*/
8408 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8409 {
8410   PetscMPIInt size;
8411   Mat        *local;
8412   IS          iscoltmp;
8413   PetscBool   flg;
8414 
8415   PetscFunctionBegin;
8416   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8417   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8418   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8419   PetscAssertPointer(newmat, 5);
8420   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8421   PetscValidType(mat, 1);
8422   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8423   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8424 
8425   MatCheckPreallocated(mat, 1);
8426   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8427 
8428   if (!iscol || isrow == iscol) {
8429     PetscBool   stride;
8430     PetscMPIInt grabentirematrix = 0, grab;
8431     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8432     if (stride) {
8433       PetscInt first, step, n, rstart, rend;
8434       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8435       if (step == 1) {
8436         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8437         if (rstart == first) {
8438           PetscCall(ISGetLocalSize(isrow, &n));
8439           if (n == rend - rstart) grabentirematrix = 1;
8440         }
8441       }
8442     }
8443     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8444     if (grab) {
8445       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8446       if (cll == MAT_INITIAL_MATRIX) {
8447         *newmat = mat;
8448         PetscCall(PetscObjectReference((PetscObject)mat));
8449       }
8450       PetscFunctionReturn(PETSC_SUCCESS);
8451     }
8452   }
8453 
8454   if (!iscol) {
8455     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8456   } else {
8457     iscoltmp = iscol;
8458   }
8459 
8460   /* if original matrix is on just one processor then use submatrix generated */
8461   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8462     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8463     goto setproperties;
8464   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8465     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8466     *newmat = *local;
8467     PetscCall(PetscFree(local));
8468     goto setproperties;
8469   } else if (!mat->ops->createsubmatrix) {
8470     /* Create a new matrix type that implements the operation using the full matrix */
8471     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8472     switch (cll) {
8473     case MAT_INITIAL_MATRIX:
8474       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8475       break;
8476     case MAT_REUSE_MATRIX:
8477       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8478       break;
8479     default:
8480       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8481     }
8482     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8483     goto setproperties;
8484   }
8485 
8486   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8487   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8488   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8489 
8490 setproperties:
8491   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8492     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8493     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8494   }
8495   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8496   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8497   PetscFunctionReturn(PETSC_SUCCESS);
8498 }
8499 
8500 /*@
8501   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8502 
8503   Not Collective
8504 
8505   Input Parameters:
8506 + A - the matrix we wish to propagate options from
8507 - B - the matrix we wish to propagate options to
8508 
8509   Level: beginner
8510 
8511   Note:
8512   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8513 
8514 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8515 @*/
8516 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8517 {
8518   PetscFunctionBegin;
8519   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8520   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8521   B->symmetry_eternal            = A->symmetry_eternal;
8522   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8523   B->symmetric                   = A->symmetric;
8524   B->structurally_symmetric      = A->structurally_symmetric;
8525   B->spd                         = A->spd;
8526   B->hermitian                   = A->hermitian;
8527   PetscFunctionReturn(PETSC_SUCCESS);
8528 }
8529 
8530 /*@
8531   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8532   used during the assembly process to store values that belong to
8533   other processors.
8534 
8535   Not Collective
8536 
8537   Input Parameters:
8538 + mat   - the matrix
8539 . size  - the initial size of the stash.
8540 - bsize - the initial size of the block-stash(if used).
8541 
8542   Options Database Keys:
8543 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8544 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8545 
8546   Level: intermediate
8547 
8548   Notes:
8549   The block-stash is used for values set with `MatSetValuesBlocked()` while
8550   the stash is used for values set with `MatSetValues()`
8551 
8552   Run with the option -info and look for output of the form
8553   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8554   to determine the appropriate value, MM, to use for size and
8555   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8556   to determine the value, BMM to use for bsize
8557 
8558 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8559 @*/
8560 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8561 {
8562   PetscFunctionBegin;
8563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8564   PetscValidType(mat, 1);
8565   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8566   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8567   PetscFunctionReturn(PETSC_SUCCESS);
8568 }
8569 
8570 /*@
8571   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8572   the matrix
8573 
8574   Neighbor-wise Collective
8575 
8576   Input Parameters:
8577 + A - the matrix
8578 . x - the vector to be multiplied by the interpolation operator
8579 - y - the vector to be added to the result
8580 
8581   Output Parameter:
8582 . w - the resulting vector
8583 
8584   Level: intermediate
8585 
8586   Notes:
8587   `w` may be the same vector as `y`.
8588 
8589   This allows one to use either the restriction or interpolation (its transpose)
8590   matrix to do the interpolation
8591 
8592 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8593 @*/
8594 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8595 {
8596   PetscInt M, N, Ny;
8597 
8598   PetscFunctionBegin;
8599   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8600   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8601   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8602   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8603   PetscCall(MatGetSize(A, &M, &N));
8604   PetscCall(VecGetSize(y, &Ny));
8605   if (M == Ny) {
8606     PetscCall(MatMultAdd(A, x, y, w));
8607   } else {
8608     PetscCall(MatMultTransposeAdd(A, x, y, w));
8609   }
8610   PetscFunctionReturn(PETSC_SUCCESS);
8611 }
8612 
8613 /*@
8614   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8615   the matrix
8616 
8617   Neighbor-wise Collective
8618 
8619   Input Parameters:
8620 + A - the matrix
8621 - x - the vector to be interpolated
8622 
8623   Output Parameter:
8624 . y - the resulting vector
8625 
8626   Level: intermediate
8627 
8628   Note:
8629   This allows one to use either the restriction or interpolation (its transpose)
8630   matrix to do the interpolation
8631 
8632 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8633 @*/
8634 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8635 {
8636   PetscInt M, N, Ny;
8637 
8638   PetscFunctionBegin;
8639   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8640   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8641   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8642   PetscCall(MatGetSize(A, &M, &N));
8643   PetscCall(VecGetSize(y, &Ny));
8644   if (M == Ny) {
8645     PetscCall(MatMult(A, x, y));
8646   } else {
8647     PetscCall(MatMultTranspose(A, x, y));
8648   }
8649   PetscFunctionReturn(PETSC_SUCCESS);
8650 }
8651 
8652 /*@
8653   MatRestrict - $y = A*x$ or $A^T*x$
8654 
8655   Neighbor-wise Collective
8656 
8657   Input Parameters:
8658 + A - the matrix
8659 - x - the vector to be restricted
8660 
8661   Output Parameter:
8662 . y - the resulting vector
8663 
8664   Level: intermediate
8665 
8666   Note:
8667   This allows one to use either the restriction or interpolation (its transpose)
8668   matrix to do the restriction
8669 
8670 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8671 @*/
8672 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8673 {
8674   PetscInt M, N, Nx;
8675 
8676   PetscFunctionBegin;
8677   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8678   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8679   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8680   PetscCall(MatGetSize(A, &M, &N));
8681   PetscCall(VecGetSize(x, &Nx));
8682   if (M == Nx) {
8683     PetscCall(MatMultTranspose(A, x, y));
8684   } else {
8685     PetscCall(MatMult(A, x, y));
8686   }
8687   PetscFunctionReturn(PETSC_SUCCESS);
8688 }
8689 
8690 /*@
8691   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8692 
8693   Neighbor-wise Collective
8694 
8695   Input Parameters:
8696 + A - the matrix
8697 . x - the input dense matrix to be multiplied
8698 - w - the input dense matrix to be added to the result
8699 
8700   Output Parameter:
8701 . y - the output dense matrix
8702 
8703   Level: intermediate
8704 
8705   Note:
8706   This allows one to use either the restriction or interpolation (its transpose)
8707   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8708   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8709 
8710 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8711 @*/
8712 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8713 {
8714   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8715   PetscBool trans = PETSC_TRUE;
8716   MatReuse  reuse = MAT_INITIAL_MATRIX;
8717 
8718   PetscFunctionBegin;
8719   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8720   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8721   PetscValidType(x, 2);
8722   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8723   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8724   PetscCall(MatGetSize(A, &M, &N));
8725   PetscCall(MatGetSize(x, &Mx, &Nx));
8726   if (N == Mx) trans = PETSC_FALSE;
8727   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);
8728   Mo = trans ? N : M;
8729   if (*y) {
8730     PetscCall(MatGetSize(*y, &My, &Ny));
8731     if (Mo == My && Nx == Ny) {
8732       reuse = MAT_REUSE_MATRIX;
8733     } else {
8734       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);
8735       PetscCall(MatDestroy(y));
8736     }
8737   }
8738 
8739   if (w && *y == w) { /* this is to minimize changes in PCMG */
8740     PetscBool flg;
8741 
8742     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8743     if (w) {
8744       PetscInt My, Ny, Mw, Nw;
8745 
8746       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8747       PetscCall(MatGetSize(*y, &My, &Ny));
8748       PetscCall(MatGetSize(w, &Mw, &Nw));
8749       if (!flg || My != Mw || Ny != Nw) w = NULL;
8750     }
8751     if (!w) {
8752       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8753       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8754       PetscCall(PetscObjectDereference((PetscObject)w));
8755     } else {
8756       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8757     }
8758   }
8759   if (!trans) {
8760     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8761   } else {
8762     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8763   }
8764   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8765   PetscFunctionReturn(PETSC_SUCCESS);
8766 }
8767 
8768 /*@
8769   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8770 
8771   Neighbor-wise Collective
8772 
8773   Input Parameters:
8774 + A - the matrix
8775 - x - the input dense matrix
8776 
8777   Output Parameter:
8778 . y - the output dense matrix
8779 
8780   Level: intermediate
8781 
8782   Note:
8783   This allows one to use either the restriction or interpolation (its transpose)
8784   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8785   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8786 
8787 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8788 @*/
8789 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8790 {
8791   PetscFunctionBegin;
8792   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8793   PetscFunctionReturn(PETSC_SUCCESS);
8794 }
8795 
8796 /*@
8797   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8798 
8799   Neighbor-wise Collective
8800 
8801   Input Parameters:
8802 + A - the matrix
8803 - x - the input dense matrix
8804 
8805   Output Parameter:
8806 . y - the output dense matrix
8807 
8808   Level: intermediate
8809 
8810   Note:
8811   This allows one to use either the restriction or interpolation (its transpose)
8812   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8813   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8814 
8815 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8816 @*/
8817 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8818 {
8819   PetscFunctionBegin;
8820   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8821   PetscFunctionReturn(PETSC_SUCCESS);
8822 }
8823 
8824 /*@
8825   MatGetNullSpace - retrieves the null space of a matrix.
8826 
8827   Logically Collective
8828 
8829   Input Parameters:
8830 + mat    - the matrix
8831 - nullsp - the null space object
8832 
8833   Level: developer
8834 
8835 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8836 @*/
8837 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8838 {
8839   PetscFunctionBegin;
8840   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8841   PetscAssertPointer(nullsp, 2);
8842   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8843   PetscFunctionReturn(PETSC_SUCCESS);
8844 }
8845 
8846 /*@C
8847   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8848 
8849   Logically Collective
8850 
8851   Input Parameters:
8852 + n   - the number of matrices
8853 - mat - the array of matrices
8854 
8855   Output Parameters:
8856 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
8857 
8858   Level: developer
8859 
8860   Note:
8861   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8862 
8863 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8864           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8865 @*/
8866 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8867 {
8868   PetscFunctionBegin;
8869   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8870   PetscAssertPointer(mat, 2);
8871   PetscAssertPointer(nullsp, 3);
8872 
8873   PetscCall(PetscCalloc1(3 * n, nullsp));
8874   for (PetscInt i = 0; i < n; i++) {
8875     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8876     (*nullsp)[i] = mat[i]->nullsp;
8877     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8878     (*nullsp)[n + i] = mat[i]->nearnullsp;
8879     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8880     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8881     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8882   }
8883   PetscFunctionReturn(PETSC_SUCCESS);
8884 }
8885 
8886 /*@C
8887   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8888 
8889   Logically Collective
8890 
8891   Input Parameters:
8892 + n      - the number of matrices
8893 . mat    - the array of matrices
8894 - nullsp - an array of null spaces
8895 
8896   Level: developer
8897 
8898   Note:
8899   Call `MatGetNullSpaces()` to create `nullsp`
8900 
8901 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8902           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
8903 @*/
8904 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8905 {
8906   PetscFunctionBegin;
8907   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8908   PetscAssertPointer(mat, 2);
8909   PetscAssertPointer(nullsp, 3);
8910   PetscAssertPointer(*nullsp, 3);
8911 
8912   for (PetscInt i = 0; i < n; i++) {
8913     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8914     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
8915     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
8916     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
8917     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
8918     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
8919     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
8920   }
8921   PetscCall(PetscFree(*nullsp));
8922   PetscFunctionReturn(PETSC_SUCCESS);
8923 }
8924 
8925 /*@
8926   MatSetNullSpace - attaches a null space to a matrix.
8927 
8928   Logically Collective
8929 
8930   Input Parameters:
8931 + mat    - the matrix
8932 - nullsp - the null space object
8933 
8934   Level: advanced
8935 
8936   Notes:
8937   This null space is used by the `KSP` linear solvers to solve singular systems.
8938 
8939   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`
8940 
8941   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
8942   to zero but the linear system will still be solved in a least squares sense.
8943 
8944   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8945   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)$.
8946   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
8947   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
8948   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$).
8949   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8950 
8951   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8952   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8953   routine also automatically calls `MatSetTransposeNullSpace()`.
8954 
8955   The user should call `MatNullSpaceDestroy()`.
8956 
8957 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8958           `KSPSetPCSide()`
8959 @*/
8960 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8961 {
8962   PetscFunctionBegin;
8963   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8964   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8965   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8966   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8967   mat->nullsp = nullsp;
8968   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8969   PetscFunctionReturn(PETSC_SUCCESS);
8970 }
8971 
8972 /*@
8973   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8974 
8975   Logically Collective
8976 
8977   Input Parameters:
8978 + mat    - the matrix
8979 - nullsp - the null space object
8980 
8981   Level: developer
8982 
8983 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8984 @*/
8985 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8986 {
8987   PetscFunctionBegin;
8988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8989   PetscValidType(mat, 1);
8990   PetscAssertPointer(nullsp, 2);
8991   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8992   PetscFunctionReturn(PETSC_SUCCESS);
8993 }
8994 
8995 /*@
8996   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8997 
8998   Logically Collective
8999 
9000   Input Parameters:
9001 + mat    - the matrix
9002 - nullsp - the null space object
9003 
9004   Level: advanced
9005 
9006   Notes:
9007   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9008 
9009   See `MatSetNullSpace()`
9010 
9011 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9012 @*/
9013 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9014 {
9015   PetscFunctionBegin;
9016   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9017   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9018   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9019   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9020   mat->transnullsp = nullsp;
9021   PetscFunctionReturn(PETSC_SUCCESS);
9022 }
9023 
9024 /*@
9025   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9026   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9027 
9028   Logically Collective
9029 
9030   Input Parameters:
9031 + mat    - the matrix
9032 - nullsp - the null space object
9033 
9034   Level: advanced
9035 
9036   Notes:
9037   Overwrites any previous near null space that may have been attached
9038 
9039   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9040 
9041 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9042 @*/
9043 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9044 {
9045   PetscFunctionBegin;
9046   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9047   PetscValidType(mat, 1);
9048   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9049   MatCheckPreallocated(mat, 1);
9050   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9051   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9052   mat->nearnullsp = nullsp;
9053   PetscFunctionReturn(PETSC_SUCCESS);
9054 }
9055 
9056 /*@
9057   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9058 
9059   Not Collective
9060 
9061   Input Parameter:
9062 . mat - the matrix
9063 
9064   Output Parameter:
9065 . nullsp - the null space object, `NULL` if not set
9066 
9067   Level: advanced
9068 
9069 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9070 @*/
9071 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9072 {
9073   PetscFunctionBegin;
9074   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9075   PetscValidType(mat, 1);
9076   PetscAssertPointer(nullsp, 2);
9077   MatCheckPreallocated(mat, 1);
9078   *nullsp = mat->nearnullsp;
9079   PetscFunctionReturn(PETSC_SUCCESS);
9080 }
9081 
9082 /*@
9083   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9084 
9085   Collective
9086 
9087   Input Parameters:
9088 + mat  - the matrix
9089 . row  - row/column permutation
9090 - info - information on desired factorization process
9091 
9092   Level: developer
9093 
9094   Notes:
9095   Probably really in-place only when level of fill is zero, otherwise allocates
9096   new space to store factored matrix and deletes previous memory.
9097 
9098   Most users should employ the `KSP` interface for linear solvers
9099   instead of working directly with matrix algebra routines such as this.
9100   See, e.g., `KSPCreate()`.
9101 
9102   Developer Note:
9103   The Fortran interface is not autogenerated as the
9104   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9105 
9106 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9107 @*/
9108 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9109 {
9110   PetscFunctionBegin;
9111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9112   PetscValidType(mat, 1);
9113   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9114   PetscAssertPointer(info, 3);
9115   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9116   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9117   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9118   MatCheckPreallocated(mat, 1);
9119   PetscUseTypeMethod(mat, iccfactor, row, info);
9120   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9121   PetscFunctionReturn(PETSC_SUCCESS);
9122 }
9123 
9124 /*@
9125   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9126   ghosted ones.
9127 
9128   Not Collective
9129 
9130   Input Parameters:
9131 + mat  - the matrix
9132 - diag - the diagonal values, including ghost ones
9133 
9134   Level: developer
9135 
9136   Notes:
9137   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9138 
9139   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9140 
9141 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9142 @*/
9143 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9144 {
9145   PetscMPIInt size;
9146 
9147   PetscFunctionBegin;
9148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9149   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9150   PetscValidType(mat, 1);
9151 
9152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9153   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9154   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9155   if (size == 1) {
9156     PetscInt n, m;
9157     PetscCall(VecGetSize(diag, &n));
9158     PetscCall(MatGetSize(mat, NULL, &m));
9159     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9160     PetscCall(MatDiagonalScale(mat, NULL, diag));
9161   } else {
9162     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9163   }
9164   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9165   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9166   PetscFunctionReturn(PETSC_SUCCESS);
9167 }
9168 
9169 /*@
9170   MatGetInertia - Gets the inertia from a factored matrix
9171 
9172   Collective
9173 
9174   Input Parameter:
9175 . mat - the matrix
9176 
9177   Output Parameters:
9178 + nneg  - number of negative eigenvalues
9179 . nzero - number of zero eigenvalues
9180 - npos  - number of positive eigenvalues
9181 
9182   Level: advanced
9183 
9184   Note:
9185   Matrix must have been factored by `MatCholeskyFactor()`
9186 
9187 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9188 @*/
9189 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9190 {
9191   PetscFunctionBegin;
9192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9193   PetscValidType(mat, 1);
9194   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9195   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9196   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9197   PetscFunctionReturn(PETSC_SUCCESS);
9198 }
9199 
9200 /*@C
9201   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9202 
9203   Neighbor-wise Collective
9204 
9205   Input Parameters:
9206 + mat - the factored matrix obtained with `MatGetFactor()`
9207 - b   - the right-hand-side vectors
9208 
9209   Output Parameter:
9210 . x - the result vectors
9211 
9212   Level: developer
9213 
9214   Note:
9215   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9216   call `MatSolves`(A,x,x).
9217 
9218 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9219 @*/
9220 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9221 {
9222   PetscFunctionBegin;
9223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9224   PetscValidType(mat, 1);
9225   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9226   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9227   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9228 
9229   MatCheckPreallocated(mat, 1);
9230   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9231   PetscUseTypeMethod(mat, solves, b, x);
9232   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9233   PetscFunctionReturn(PETSC_SUCCESS);
9234 }
9235 
9236 /*@
9237   MatIsSymmetric - Test whether a matrix is symmetric
9238 
9239   Collective
9240 
9241   Input Parameters:
9242 + A   - the matrix to test
9243 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9244 
9245   Output Parameter:
9246 . flg - the result
9247 
9248   Level: intermediate
9249 
9250   Notes:
9251   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9252 
9253   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9254 
9255   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9256   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9257 
9258 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9259           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9260 @*/
9261 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9262 {
9263   PetscFunctionBegin;
9264   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9265   PetscAssertPointer(flg, 3);
9266   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9267   else {
9268     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9269     else PetscCall(MatIsTranspose(A, A, tol, flg));
9270     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9271   }
9272   PetscFunctionReturn(PETSC_SUCCESS);
9273 }
9274 
9275 /*@
9276   MatIsHermitian - Test whether a matrix is Hermitian
9277 
9278   Collective
9279 
9280   Input Parameters:
9281 + A   - the matrix to test
9282 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9283 
9284   Output Parameter:
9285 . flg - the result
9286 
9287   Level: intermediate
9288 
9289   Notes:
9290   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9291 
9292   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9293 
9294   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9295   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9296 
9297 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9298           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9299 @*/
9300 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9301 {
9302   PetscFunctionBegin;
9303   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9304   PetscAssertPointer(flg, 3);
9305   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9306   else {
9307     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9308     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9309     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9310   }
9311   PetscFunctionReturn(PETSC_SUCCESS);
9312 }
9313 
9314 /*@
9315   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9316 
9317   Not Collective
9318 
9319   Input Parameter:
9320 . A - the matrix to check
9321 
9322   Output Parameters:
9323 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9324 - flg - the result (only valid if set is `PETSC_TRUE`)
9325 
9326   Level: advanced
9327 
9328   Notes:
9329   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9330   if you want it explicitly checked
9331 
9332   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9333   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9334 
9335 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9336 @*/
9337 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9338 {
9339   PetscFunctionBegin;
9340   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9341   PetscAssertPointer(set, 2);
9342   PetscAssertPointer(flg, 3);
9343   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9344     *set = PETSC_TRUE;
9345     *flg = PetscBool3ToBool(A->symmetric);
9346   } else {
9347     *set = PETSC_FALSE;
9348   }
9349   PetscFunctionReturn(PETSC_SUCCESS);
9350 }
9351 
9352 /*@
9353   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9354 
9355   Not Collective
9356 
9357   Input Parameter:
9358 . A - the matrix to check
9359 
9360   Output Parameters:
9361 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9362 - flg - the result (only valid if set is `PETSC_TRUE`)
9363 
9364   Level: advanced
9365 
9366   Notes:
9367   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9368 
9369   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9370   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9371 
9372 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9373 @*/
9374 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9375 {
9376   PetscFunctionBegin;
9377   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9378   PetscAssertPointer(set, 2);
9379   PetscAssertPointer(flg, 3);
9380   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9381     *set = PETSC_TRUE;
9382     *flg = PetscBool3ToBool(A->spd);
9383   } else {
9384     *set = PETSC_FALSE;
9385   }
9386   PetscFunctionReturn(PETSC_SUCCESS);
9387 }
9388 
9389 /*@
9390   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9391 
9392   Not Collective
9393 
9394   Input Parameter:
9395 . A - the matrix to check
9396 
9397   Output Parameters:
9398 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9399 - flg - the result (only valid if set is `PETSC_TRUE`)
9400 
9401   Level: advanced
9402 
9403   Notes:
9404   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9405   if you want it explicitly checked
9406 
9407   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9408   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9409 
9410 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9411 @*/
9412 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9413 {
9414   PetscFunctionBegin;
9415   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9416   PetscAssertPointer(set, 2);
9417   PetscAssertPointer(flg, 3);
9418   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9419     *set = PETSC_TRUE;
9420     *flg = PetscBool3ToBool(A->hermitian);
9421   } else {
9422     *set = PETSC_FALSE;
9423   }
9424   PetscFunctionReturn(PETSC_SUCCESS);
9425 }
9426 
9427 /*@
9428   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9429 
9430   Collective
9431 
9432   Input Parameter:
9433 . A - the matrix to test
9434 
9435   Output Parameter:
9436 . flg - the result
9437 
9438   Level: intermediate
9439 
9440   Notes:
9441   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9442 
9443   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
9444   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9445 
9446 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9447 @*/
9448 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9449 {
9450   PetscFunctionBegin;
9451   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9452   PetscAssertPointer(flg, 2);
9453   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9454     *flg = PetscBool3ToBool(A->structurally_symmetric);
9455   } else {
9456     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9457     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9458   }
9459   PetscFunctionReturn(PETSC_SUCCESS);
9460 }
9461 
9462 /*@
9463   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9464 
9465   Not Collective
9466 
9467   Input Parameter:
9468 . A - the matrix to check
9469 
9470   Output Parameters:
9471 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9472 - flg - the result (only valid if set is PETSC_TRUE)
9473 
9474   Level: advanced
9475 
9476   Notes:
9477   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
9478   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9479 
9480   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9481 
9482 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9483 @*/
9484 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9485 {
9486   PetscFunctionBegin;
9487   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9488   PetscAssertPointer(set, 2);
9489   PetscAssertPointer(flg, 3);
9490   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9491     *set = PETSC_TRUE;
9492     *flg = PetscBool3ToBool(A->structurally_symmetric);
9493   } else {
9494     *set = PETSC_FALSE;
9495   }
9496   PetscFunctionReturn(PETSC_SUCCESS);
9497 }
9498 
9499 /*@
9500   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9501   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9502 
9503   Not Collective
9504 
9505   Input Parameter:
9506 . mat - the matrix
9507 
9508   Output Parameters:
9509 + nstash    - the size of the stash
9510 . reallocs  - the number of additional mallocs incurred.
9511 . bnstash   - the size of the block stash
9512 - breallocs - the number of additional mallocs incurred.in the block stash
9513 
9514   Level: advanced
9515 
9516 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9517 @*/
9518 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9519 {
9520   PetscFunctionBegin;
9521   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9522   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9523   PetscFunctionReturn(PETSC_SUCCESS);
9524 }
9525 
9526 /*@
9527   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9528   parallel layout, `PetscLayout` for rows and columns
9529 
9530   Collective
9531 
9532   Input Parameter:
9533 . mat - the matrix
9534 
9535   Output Parameters:
9536 + right - (optional) vector that the matrix can be multiplied against
9537 - left  - (optional) vector that the matrix vector product can be stored in
9538 
9539   Level: advanced
9540 
9541   Notes:
9542   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()`.
9543 
9544   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9545 
9546 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9547 @*/
9548 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9549 {
9550   PetscFunctionBegin;
9551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9552   PetscValidType(mat, 1);
9553   if (mat->ops->getvecs) {
9554     PetscUseTypeMethod(mat, getvecs, right, left);
9555   } else {
9556     if (right) {
9557       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9558       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9559       PetscCall(VecSetType(*right, mat->defaultvectype));
9560 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9561       if (mat->boundtocpu && mat->bindingpropagates) {
9562         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9563         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9564       }
9565 #endif
9566     }
9567     if (left) {
9568       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9569       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9570       PetscCall(VecSetType(*left, mat->defaultvectype));
9571 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9572       if (mat->boundtocpu && mat->bindingpropagates) {
9573         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9574         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9575       }
9576 #endif
9577     }
9578   }
9579   PetscFunctionReturn(PETSC_SUCCESS);
9580 }
9581 
9582 /*@
9583   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9584   with default values.
9585 
9586   Not Collective
9587 
9588   Input Parameter:
9589 . info - the `MatFactorInfo` data structure
9590 
9591   Level: developer
9592 
9593   Notes:
9594   The solvers are generally used through the `KSP` and `PC` objects, for example
9595   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9596 
9597   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9598 
9599 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9600 @*/
9601 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9602 {
9603   PetscFunctionBegin;
9604   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9605   PetscFunctionReturn(PETSC_SUCCESS);
9606 }
9607 
9608 /*@
9609   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9610 
9611   Collective
9612 
9613   Input Parameters:
9614 + mat - the factored matrix
9615 - is  - the index set defining the Schur indices (0-based)
9616 
9617   Level: advanced
9618 
9619   Notes:
9620   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9621 
9622   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9623 
9624   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9625 
9626 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9627           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9628 @*/
9629 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9630 {
9631   PetscErrorCode (*f)(Mat, IS);
9632 
9633   PetscFunctionBegin;
9634   PetscValidType(mat, 1);
9635   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9636   PetscValidType(is, 2);
9637   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9638   PetscCheckSameComm(mat, 1, is, 2);
9639   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9640   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9641   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9642   PetscCall(MatDestroy(&mat->schur));
9643   PetscCall((*f)(mat, is));
9644   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9645   PetscFunctionReturn(PETSC_SUCCESS);
9646 }
9647 
9648 /*@
9649   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9650 
9651   Logically Collective
9652 
9653   Input Parameters:
9654 + F      - the factored matrix obtained by calling `MatGetFactor()`
9655 . S      - location where to return the Schur complement, can be `NULL`
9656 - status - the status of the Schur complement matrix, can be `NULL`
9657 
9658   Level: advanced
9659 
9660   Notes:
9661   You must call `MatFactorSetSchurIS()` before calling this routine.
9662 
9663   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9664 
9665   The routine provides a copy of the Schur matrix stored within the solver data structures.
9666   The caller must destroy the object when it is no longer needed.
9667   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9668 
9669   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)
9670 
9671   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9672 
9673   Developer Note:
9674   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9675   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9676 
9677 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9678 @*/
9679 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9680 {
9681   PetscFunctionBegin;
9682   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9683   if (S) PetscAssertPointer(S, 2);
9684   if (status) PetscAssertPointer(status, 3);
9685   if (S) {
9686     PetscErrorCode (*f)(Mat, Mat *);
9687 
9688     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9689     if (f) {
9690       PetscCall((*f)(F, S));
9691     } else {
9692       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9693     }
9694   }
9695   if (status) *status = F->schur_status;
9696   PetscFunctionReturn(PETSC_SUCCESS);
9697 }
9698 
9699 /*@
9700   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9701 
9702   Logically Collective
9703 
9704   Input Parameters:
9705 + F      - the factored matrix obtained by calling `MatGetFactor()`
9706 . S      - location where to return the Schur complement, can be `NULL`
9707 - status - the status of the Schur complement matrix, can be `NULL`
9708 
9709   Level: advanced
9710 
9711   Notes:
9712   You must call `MatFactorSetSchurIS()` before calling this routine.
9713 
9714   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9715 
9716   The routine returns a the Schur Complement stored within the data structures of the solver.
9717 
9718   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9719 
9720   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9721 
9722   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9723 
9724   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9725 
9726 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9727 @*/
9728 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9729 {
9730   PetscFunctionBegin;
9731   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9732   if (S) {
9733     PetscAssertPointer(S, 2);
9734     *S = F->schur;
9735   }
9736   if (status) {
9737     PetscAssertPointer(status, 3);
9738     *status = F->schur_status;
9739   }
9740   PetscFunctionReturn(PETSC_SUCCESS);
9741 }
9742 
9743 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9744 {
9745   Mat S = F->schur;
9746 
9747   PetscFunctionBegin;
9748   switch (F->schur_status) {
9749   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9750   case MAT_FACTOR_SCHUR_INVERTED:
9751     if (S) {
9752       S->ops->solve             = NULL;
9753       S->ops->matsolve          = NULL;
9754       S->ops->solvetranspose    = NULL;
9755       S->ops->matsolvetranspose = NULL;
9756       S->ops->solveadd          = NULL;
9757       S->ops->solvetransposeadd = NULL;
9758       S->factortype             = MAT_FACTOR_NONE;
9759       PetscCall(PetscFree(S->solvertype));
9760     }
9761   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9762     break;
9763   default:
9764     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9765   }
9766   PetscFunctionReturn(PETSC_SUCCESS);
9767 }
9768 
9769 /*@
9770   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9771 
9772   Logically Collective
9773 
9774   Input Parameters:
9775 + F      - the factored matrix obtained by calling `MatGetFactor()`
9776 . S      - location where the Schur complement is stored
9777 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9778 
9779   Level: advanced
9780 
9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9782 @*/
9783 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9784 {
9785   PetscFunctionBegin;
9786   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9787   if (S) {
9788     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9789     *S = NULL;
9790   }
9791   F->schur_status = status;
9792   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9793   PetscFunctionReturn(PETSC_SUCCESS);
9794 }
9795 
9796 /*@
9797   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9798 
9799   Logically Collective
9800 
9801   Input Parameters:
9802 + F   - the factored matrix obtained by calling `MatGetFactor()`
9803 . rhs - location where the right-hand side of the Schur complement system is stored
9804 - sol - location where the solution of the Schur complement system has to be returned
9805 
9806   Level: advanced
9807 
9808   Notes:
9809   The sizes of the vectors should match the size of the Schur complement
9810 
9811   Must be called after `MatFactorSetSchurIS()`
9812 
9813 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9814 @*/
9815 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9816 {
9817   PetscFunctionBegin;
9818   PetscValidType(F, 1);
9819   PetscValidType(rhs, 2);
9820   PetscValidType(sol, 3);
9821   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9822   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9823   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9824   PetscCheckSameComm(F, 1, rhs, 2);
9825   PetscCheckSameComm(F, 1, sol, 3);
9826   PetscCall(MatFactorFactorizeSchurComplement(F));
9827   switch (F->schur_status) {
9828   case MAT_FACTOR_SCHUR_FACTORED:
9829     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9830     break;
9831   case MAT_FACTOR_SCHUR_INVERTED:
9832     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9833     break;
9834   default:
9835     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9836   }
9837   PetscFunctionReturn(PETSC_SUCCESS);
9838 }
9839 
9840 /*@
9841   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9842 
9843   Logically Collective
9844 
9845   Input Parameters:
9846 + F   - the factored matrix obtained by calling `MatGetFactor()`
9847 . rhs - location where the right-hand side of the Schur complement system is stored
9848 - sol - location where the solution of the Schur complement system has to be returned
9849 
9850   Level: advanced
9851 
9852   Notes:
9853   The sizes of the vectors should match the size of the Schur complement
9854 
9855   Must be called after `MatFactorSetSchurIS()`
9856 
9857 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9858 @*/
9859 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9860 {
9861   PetscFunctionBegin;
9862   PetscValidType(F, 1);
9863   PetscValidType(rhs, 2);
9864   PetscValidType(sol, 3);
9865   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9866   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9867   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9868   PetscCheckSameComm(F, 1, rhs, 2);
9869   PetscCheckSameComm(F, 1, sol, 3);
9870   PetscCall(MatFactorFactorizeSchurComplement(F));
9871   switch (F->schur_status) {
9872   case MAT_FACTOR_SCHUR_FACTORED:
9873     PetscCall(MatSolve(F->schur, rhs, sol));
9874     break;
9875   case MAT_FACTOR_SCHUR_INVERTED:
9876     PetscCall(MatMult(F->schur, rhs, sol));
9877     break;
9878   default:
9879     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9880   }
9881   PetscFunctionReturn(PETSC_SUCCESS);
9882 }
9883 
9884 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9885 #if PetscDefined(HAVE_CUDA)
9886 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9887 #endif
9888 
9889 /* Schur status updated in the interface */
9890 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9891 {
9892   Mat S = F->schur;
9893 
9894   PetscFunctionBegin;
9895   if (S) {
9896     PetscMPIInt size;
9897     PetscBool   isdense, isdensecuda;
9898 
9899     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9900     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9901     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9902     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9903     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9904     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9905     if (isdense) {
9906       PetscCall(MatSeqDenseInvertFactors_Private(S));
9907     } else if (isdensecuda) {
9908 #if defined(PETSC_HAVE_CUDA)
9909       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9910 #endif
9911     }
9912     // HIP??????????????
9913     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9914   }
9915   PetscFunctionReturn(PETSC_SUCCESS);
9916 }
9917 
9918 /*@
9919   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9920 
9921   Logically Collective
9922 
9923   Input Parameter:
9924 . F - the factored matrix obtained by calling `MatGetFactor()`
9925 
9926   Level: advanced
9927 
9928   Notes:
9929   Must be called after `MatFactorSetSchurIS()`.
9930 
9931   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9932 
9933 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9934 @*/
9935 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9936 {
9937   PetscFunctionBegin;
9938   PetscValidType(F, 1);
9939   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9940   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9941   PetscCall(MatFactorFactorizeSchurComplement(F));
9942   PetscCall(MatFactorInvertSchurComplement_Private(F));
9943   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9944   PetscFunctionReturn(PETSC_SUCCESS);
9945 }
9946 
9947 /*@
9948   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9949 
9950   Logically Collective
9951 
9952   Input Parameter:
9953 . F - the factored matrix obtained by calling `MatGetFactor()`
9954 
9955   Level: advanced
9956 
9957   Note:
9958   Must be called after `MatFactorSetSchurIS()`
9959 
9960 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9961 @*/
9962 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9963 {
9964   MatFactorInfo info;
9965 
9966   PetscFunctionBegin;
9967   PetscValidType(F, 1);
9968   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9969   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9970   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9971   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9972   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9973     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9974   } else {
9975     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9976   }
9977   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9978   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9979   PetscFunctionReturn(PETSC_SUCCESS);
9980 }
9981 
9982 /*@
9983   MatPtAP - Creates the matrix product $C = P^T * A * P$
9984 
9985   Neighbor-wise Collective
9986 
9987   Input Parameters:
9988 + A     - the matrix
9989 . P     - the projection matrix
9990 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9991 - 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
9992           if the result is a dense matrix this is irrelevant
9993 
9994   Output Parameter:
9995 . C - the product matrix
9996 
9997   Level: intermediate
9998 
9999   Notes:
10000   C will be created and must be destroyed by the user with `MatDestroy()`.
10001 
10002   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10003 
10004   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10005 
10006   Developer Note:
10007   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10008 
10009 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10010 @*/
10011 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10012 {
10013   PetscFunctionBegin;
10014   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10015   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10016 
10017   if (scall == MAT_INITIAL_MATRIX) {
10018     PetscCall(MatProductCreate(A, P, NULL, C));
10019     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10020     PetscCall(MatProductSetAlgorithm(*C, "default"));
10021     PetscCall(MatProductSetFill(*C, fill));
10022 
10023     (*C)->product->api_user = PETSC_TRUE;
10024     PetscCall(MatProductSetFromOptions(*C));
10025     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);
10026     PetscCall(MatProductSymbolic(*C));
10027   } else { /* scall == MAT_REUSE_MATRIX */
10028     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10029   }
10030 
10031   PetscCall(MatProductNumeric(*C));
10032   (*C)->symmetric = A->symmetric;
10033   (*C)->spd       = A->spd;
10034   PetscFunctionReturn(PETSC_SUCCESS);
10035 }
10036 
10037 /*@
10038   MatRARt - Creates the matrix product $C = R * A * R^T$
10039 
10040   Neighbor-wise Collective
10041 
10042   Input Parameters:
10043 + A     - the matrix
10044 . R     - the projection matrix
10045 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10046 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10047           if the result is a dense matrix this is irrelevant
10048 
10049   Output Parameter:
10050 . C - the product matrix
10051 
10052   Level: intermediate
10053 
10054   Notes:
10055   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10056 
10057   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10058 
10059   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10060   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10061   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10062   We recommend using `MatPtAP()` when possible.
10063 
10064   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10065 
10066 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10067 @*/
10068 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10069 {
10070   PetscFunctionBegin;
10071   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10072   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10073 
10074   if (scall == MAT_INITIAL_MATRIX) {
10075     PetscCall(MatProductCreate(A, R, NULL, C));
10076     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10077     PetscCall(MatProductSetAlgorithm(*C, "default"));
10078     PetscCall(MatProductSetFill(*C, fill));
10079 
10080     (*C)->product->api_user = PETSC_TRUE;
10081     PetscCall(MatProductSetFromOptions(*C));
10082     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);
10083     PetscCall(MatProductSymbolic(*C));
10084   } else { /* scall == MAT_REUSE_MATRIX */
10085     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10086   }
10087 
10088   PetscCall(MatProductNumeric(*C));
10089   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10090   PetscFunctionReturn(PETSC_SUCCESS);
10091 }
10092 
10093 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10094 {
10095   PetscBool flg = PETSC_TRUE;
10096 
10097   PetscFunctionBegin;
10098   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10099   if (scall == MAT_INITIAL_MATRIX) {
10100     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10101     PetscCall(MatProductCreate(A, B, NULL, C));
10102     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10103     PetscCall(MatProductSetFill(*C, fill));
10104   } else { /* scall == MAT_REUSE_MATRIX */
10105     Mat_Product *product = (*C)->product;
10106 
10107     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10108     if (flg && product && product->type != ptype) {
10109       PetscCall(MatProductClear(*C));
10110       product = NULL;
10111     }
10112     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10113     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10114       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10115       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10116       product        = (*C)->product;
10117       product->fill  = fill;
10118       product->clear = PETSC_TRUE;
10119     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10120       flg = PETSC_FALSE;
10121       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10122     }
10123   }
10124   if (flg) {
10125     (*C)->product->api_user = PETSC_TRUE;
10126     PetscCall(MatProductSetType(*C, ptype));
10127     PetscCall(MatProductSetFromOptions(*C));
10128     PetscCall(MatProductSymbolic(*C));
10129   }
10130   PetscCall(MatProductNumeric(*C));
10131   PetscFunctionReturn(PETSC_SUCCESS);
10132 }
10133 
10134 /*@
10135   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10136 
10137   Neighbor-wise Collective
10138 
10139   Input Parameters:
10140 + A     - the left matrix
10141 . B     - the right matrix
10142 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10143 - 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
10144           if the result is a dense matrix this is irrelevant
10145 
10146   Output Parameter:
10147 . C - the product matrix
10148 
10149   Notes:
10150   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10151 
10152   `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
10153   call to this function with `MAT_INITIAL_MATRIX`.
10154 
10155   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10156 
10157   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`,
10158   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10159 
10160   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10161 
10162   Example of Usage:
10163 .vb
10164      MatProductCreate(A,B,NULL,&C);
10165      MatProductSetType(C,MATPRODUCT_AB);
10166      MatProductSymbolic(C);
10167      MatProductNumeric(C); // compute C=A * B
10168      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10169      MatProductNumeric(C);
10170      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10171      MatProductNumeric(C);
10172 .ve
10173 
10174   Level: intermediate
10175 
10176 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10177 @*/
10178 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10179 {
10180   PetscFunctionBegin;
10181   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10182   PetscFunctionReturn(PETSC_SUCCESS);
10183 }
10184 
10185 /*@
10186   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10187 
10188   Neighbor-wise Collective
10189 
10190   Input Parameters:
10191 + A     - the left matrix
10192 . B     - the right matrix
10193 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10194 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10195 
10196   Output Parameter:
10197 . C - the product matrix
10198 
10199   Options Database Key:
10200 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10201               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10202               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10203 
10204   Level: intermediate
10205 
10206   Notes:
10207   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10208 
10209   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10210 
10211   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10212   actually needed.
10213 
10214   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10215   and for pairs of `MATMPIDENSE` matrices.
10216 
10217   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10218 
10219   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10220 
10221 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10222 @*/
10223 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10224 {
10225   PetscFunctionBegin;
10226   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10227   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10228   PetscFunctionReturn(PETSC_SUCCESS);
10229 }
10230 
10231 /*@
10232   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10233 
10234   Neighbor-wise Collective
10235 
10236   Input Parameters:
10237 + A     - the left matrix
10238 . B     - the right matrix
10239 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10240 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10241 
10242   Output Parameter:
10243 . C - the product matrix
10244 
10245   Level: intermediate
10246 
10247   Notes:
10248   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10249 
10250   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10251 
10252   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10253 
10254   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10255   actually needed.
10256 
10257   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10258   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10259 
10260   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10261 
10262 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10263 @*/
10264 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10265 {
10266   PetscFunctionBegin;
10267   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10268   PetscFunctionReturn(PETSC_SUCCESS);
10269 }
10270 
10271 /*@
10272   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10273 
10274   Neighbor-wise Collective
10275 
10276   Input Parameters:
10277 + A     - the left matrix
10278 . B     - the middle matrix
10279 . C     - the right matrix
10280 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10281 - 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
10282           if the result is a dense matrix this is irrelevant
10283 
10284   Output Parameter:
10285 . D - the product matrix
10286 
10287   Level: intermediate
10288 
10289   Notes:
10290   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10291 
10292   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10293 
10294   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10295 
10296   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10297   actually needed.
10298 
10299   If you have many matrices with the same non-zero structure to multiply, you
10300   should use `MAT_REUSE_MATRIX` in all calls but the first
10301 
10302   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10303 
10304 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10305 @*/
10306 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10307 {
10308   PetscFunctionBegin;
10309   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10310   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10311 
10312   if (scall == MAT_INITIAL_MATRIX) {
10313     PetscCall(MatProductCreate(A, B, C, D));
10314     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10315     PetscCall(MatProductSetAlgorithm(*D, "default"));
10316     PetscCall(MatProductSetFill(*D, fill));
10317 
10318     (*D)->product->api_user = PETSC_TRUE;
10319     PetscCall(MatProductSetFromOptions(*D));
10320     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,
10321                ((PetscObject)C)->type_name);
10322     PetscCall(MatProductSymbolic(*D));
10323   } else { /* user may change input matrices when REUSE */
10324     PetscCall(MatProductReplaceMats(A, B, C, *D));
10325   }
10326   PetscCall(MatProductNumeric(*D));
10327   PetscFunctionReturn(PETSC_SUCCESS);
10328 }
10329 
10330 /*@
10331   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10332 
10333   Collective
10334 
10335   Input Parameters:
10336 + mat      - the matrix
10337 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10338 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10339 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10340 
10341   Output Parameter:
10342 . matredundant - redundant matrix
10343 
10344   Level: advanced
10345 
10346   Notes:
10347   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10348   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10349 
10350   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10351   calling it.
10352 
10353   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10354 
10355 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10356 @*/
10357 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10358 {
10359   MPI_Comm       comm;
10360   PetscMPIInt    size;
10361   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10362   Mat_Redundant *redund     = NULL;
10363   PetscSubcomm   psubcomm   = NULL;
10364   MPI_Comm       subcomm_in = subcomm;
10365   Mat           *matseq;
10366   IS             isrow, iscol;
10367   PetscBool      newsubcomm = PETSC_FALSE;
10368 
10369   PetscFunctionBegin;
10370   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10371   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10372     PetscAssertPointer(*matredundant, 5);
10373     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10374   }
10375 
10376   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10377   if (size == 1 || nsubcomm == 1) {
10378     if (reuse == MAT_INITIAL_MATRIX) {
10379       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10380     } else {
10381       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");
10382       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10383     }
10384     PetscFunctionReturn(PETSC_SUCCESS);
10385   }
10386 
10387   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10388   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10389   MatCheckPreallocated(mat, 1);
10390 
10391   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10392   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10393     /* create psubcomm, then get subcomm */
10394     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10395     PetscCallMPI(MPI_Comm_size(comm, &size));
10396     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10397 
10398     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10399     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10400     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10401     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10402     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10403     newsubcomm = PETSC_TRUE;
10404     PetscCall(PetscSubcommDestroy(&psubcomm));
10405   }
10406 
10407   /* get isrow, iscol and a local sequential matrix matseq[0] */
10408   if (reuse == MAT_INITIAL_MATRIX) {
10409     mloc_sub = PETSC_DECIDE;
10410     nloc_sub = PETSC_DECIDE;
10411     if (bs < 1) {
10412       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10413       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10414     } else {
10415       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10416       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10417     }
10418     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10419     rstart = rend - mloc_sub;
10420     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10421     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10422     PetscCall(ISSetIdentity(iscol));
10423   } else { /* reuse == MAT_REUSE_MATRIX */
10424     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");
10425     /* retrieve subcomm */
10426     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10427     redund = (*matredundant)->redundant;
10428     isrow  = redund->isrow;
10429     iscol  = redund->iscol;
10430     matseq = redund->matseq;
10431   }
10432   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10433 
10434   /* get matredundant over subcomm */
10435   if (reuse == MAT_INITIAL_MATRIX) {
10436     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10437 
10438     /* create a supporting struct and attach it to C for reuse */
10439     PetscCall(PetscNew(&redund));
10440     (*matredundant)->redundant = redund;
10441     redund->isrow              = isrow;
10442     redund->iscol              = iscol;
10443     redund->matseq             = matseq;
10444     if (newsubcomm) {
10445       redund->subcomm = subcomm;
10446     } else {
10447       redund->subcomm = MPI_COMM_NULL;
10448     }
10449   } else {
10450     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10451   }
10452 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10453   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10454     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10455     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10456   }
10457 #endif
10458   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10459   PetscFunctionReturn(PETSC_SUCCESS);
10460 }
10461 
10462 /*@C
10463   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10464   a given `Mat`. Each submatrix can span multiple procs.
10465 
10466   Collective
10467 
10468   Input Parameters:
10469 + mat     - the matrix
10470 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10471 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10472 
10473   Output Parameter:
10474 . subMat - parallel sub-matrices each spanning a given `subcomm`
10475 
10476   Level: advanced
10477 
10478   Notes:
10479   The submatrix partition across processors is dictated by `subComm` a
10480   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10481   is not restricted to be grouped with consecutive original MPI processes.
10482 
10483   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10484   map directly to the layout of the original matrix [wrt the local
10485   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10486   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10487   the `subMat`. However the offDiagMat looses some columns - and this is
10488   reconstructed with `MatSetValues()`
10489 
10490   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10491 
10492 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10493 @*/
10494 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10495 {
10496   PetscMPIInt commsize, subCommSize;
10497 
10498   PetscFunctionBegin;
10499   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10500   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10501   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10502 
10503   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");
10504   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10505   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10506   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10507   PetscFunctionReturn(PETSC_SUCCESS);
10508 }
10509 
10510 /*@
10511   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10512 
10513   Not Collective
10514 
10515   Input Parameters:
10516 + mat   - matrix to extract local submatrix from
10517 . isrow - local row indices for submatrix
10518 - iscol - local column indices for submatrix
10519 
10520   Output Parameter:
10521 . submat - the submatrix
10522 
10523   Level: intermediate
10524 
10525   Notes:
10526   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10527 
10528   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10529   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10530 
10531   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10532   `MatSetValuesBlockedLocal()` will also be implemented.
10533 
10534   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10535   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10536 
10537 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10538 @*/
10539 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10540 {
10541   PetscFunctionBegin;
10542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10543   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10544   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10545   PetscCheckSameComm(isrow, 2, iscol, 3);
10546   PetscAssertPointer(submat, 4);
10547   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10548 
10549   if (mat->ops->getlocalsubmatrix) {
10550     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10551   } else {
10552     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10553   }
10554   PetscFunctionReturn(PETSC_SUCCESS);
10555 }
10556 
10557 /*@
10558   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10559 
10560   Not Collective
10561 
10562   Input Parameters:
10563 + mat    - matrix to extract local submatrix from
10564 . isrow  - local row indices for submatrix
10565 . iscol  - local column indices for submatrix
10566 - submat - the submatrix
10567 
10568   Level: intermediate
10569 
10570 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10571 @*/
10572 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10573 {
10574   PetscFunctionBegin;
10575   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10576   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10577   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10578   PetscCheckSameComm(isrow, 2, iscol, 3);
10579   PetscAssertPointer(submat, 4);
10580   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10581 
10582   if (mat->ops->restorelocalsubmatrix) {
10583     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10584   } else {
10585     PetscCall(MatDestroy(submat));
10586   }
10587   *submat = NULL;
10588   PetscFunctionReturn(PETSC_SUCCESS);
10589 }
10590 
10591 /*@
10592   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10593 
10594   Collective
10595 
10596   Input Parameter:
10597 . mat - the matrix
10598 
10599   Output Parameter:
10600 . is - if any rows have zero diagonals this contains the list of them
10601 
10602   Level: developer
10603 
10604 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10605 @*/
10606 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10607 {
10608   PetscFunctionBegin;
10609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10610   PetscValidType(mat, 1);
10611   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10612   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10613 
10614   if (!mat->ops->findzerodiagonals) {
10615     Vec                diag;
10616     const PetscScalar *a;
10617     PetscInt          *rows;
10618     PetscInt           rStart, rEnd, r, nrow = 0;
10619 
10620     PetscCall(MatCreateVecs(mat, &diag, NULL));
10621     PetscCall(MatGetDiagonal(mat, diag));
10622     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10623     PetscCall(VecGetArrayRead(diag, &a));
10624     for (r = 0; r < rEnd - rStart; ++r)
10625       if (a[r] == 0.0) ++nrow;
10626     PetscCall(PetscMalloc1(nrow, &rows));
10627     nrow = 0;
10628     for (r = 0; r < rEnd - rStart; ++r)
10629       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10630     PetscCall(VecRestoreArrayRead(diag, &a));
10631     PetscCall(VecDestroy(&diag));
10632     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10633   } else {
10634     PetscUseTypeMethod(mat, findzerodiagonals, is);
10635   }
10636   PetscFunctionReturn(PETSC_SUCCESS);
10637 }
10638 
10639 /*@
10640   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10641 
10642   Collective
10643 
10644   Input Parameter:
10645 . mat - the matrix
10646 
10647   Output Parameter:
10648 . is - contains the list of rows with off block diagonal entries
10649 
10650   Level: developer
10651 
10652 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10653 @*/
10654 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10655 {
10656   PetscFunctionBegin;
10657   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10658   PetscValidType(mat, 1);
10659   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10660   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10661 
10662   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10663   PetscFunctionReturn(PETSC_SUCCESS);
10664 }
10665 
10666 /*@C
10667   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10668 
10669   Collective; No Fortran Support
10670 
10671   Input Parameter:
10672 . mat - the matrix
10673 
10674   Output Parameter:
10675 . values - the block inverses in column major order (FORTRAN-like)
10676 
10677   Level: advanced
10678 
10679   Notes:
10680   The size of the blocks is determined by the block size of the matrix.
10681 
10682   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10683 
10684   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10685 
10686 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10687 @*/
10688 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10689 {
10690   PetscFunctionBegin;
10691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10692   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10693   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10694   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10695   PetscFunctionReturn(PETSC_SUCCESS);
10696 }
10697 
10698 /*@
10699   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10700 
10701   Collective; No Fortran Support
10702 
10703   Input Parameters:
10704 + mat     - the matrix
10705 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10706 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10707 
10708   Output Parameter:
10709 . values - the block inverses in column major order (FORTRAN-like)
10710 
10711   Level: advanced
10712 
10713   Notes:
10714   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10715 
10716   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10717 
10718 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10719 @*/
10720 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10721 {
10722   PetscFunctionBegin;
10723   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10724   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10725   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10726   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10727   PetscFunctionReturn(PETSC_SUCCESS);
10728 }
10729 
10730 /*@
10731   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10732 
10733   Collective
10734 
10735   Input Parameters:
10736 + A - the matrix
10737 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10738 
10739   Level: advanced
10740 
10741   Note:
10742   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10743 
10744 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10745 @*/
10746 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10747 {
10748   const PetscScalar *vals;
10749   PetscInt          *dnnz;
10750   PetscInt           m, rstart, rend, bs, i, j;
10751 
10752   PetscFunctionBegin;
10753   PetscCall(MatInvertBlockDiagonal(A, &vals));
10754   PetscCall(MatGetBlockSize(A, &bs));
10755   PetscCall(MatGetLocalSize(A, &m, NULL));
10756   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10757   if (A->rmap->bs > 1) PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); // mpiaij to A and B
10758   PetscCall(PetscMalloc1(m / bs, &dnnz));
10759   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10760   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10761   PetscCall(PetscFree(dnnz));
10762   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10763   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10764   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10765   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10766   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10767   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10768   PetscFunctionReturn(PETSC_SUCCESS);
10769 }
10770 
10771 /*@
10772   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10773   via `MatTransposeColoringCreate()`.
10774 
10775   Collective
10776 
10777   Input Parameter:
10778 . c - coloring context
10779 
10780   Level: intermediate
10781 
10782 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10783 @*/
10784 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10785 {
10786   MatTransposeColoring matcolor = *c;
10787 
10788   PetscFunctionBegin;
10789   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10790   if (--((PetscObject)matcolor)->refct > 0) {
10791     matcolor = NULL;
10792     PetscFunctionReturn(PETSC_SUCCESS);
10793   }
10794 
10795   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10796   PetscCall(PetscFree(matcolor->rows));
10797   PetscCall(PetscFree(matcolor->den2sp));
10798   PetscCall(PetscFree(matcolor->colorforcol));
10799   PetscCall(PetscFree(matcolor->columns));
10800   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10801   PetscCall(PetscHeaderDestroy(c));
10802   PetscFunctionReturn(PETSC_SUCCESS);
10803 }
10804 
10805 /*@
10806   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10807   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10808   `MatTransposeColoring` to sparse `B`.
10809 
10810   Collective
10811 
10812   Input Parameters:
10813 + coloring - coloring context created with `MatTransposeColoringCreate()`
10814 - B        - sparse matrix
10815 
10816   Output Parameter:
10817 . Btdense - dense matrix $B^T$
10818 
10819   Level: developer
10820 
10821   Note:
10822   These are used internally for some implementations of `MatRARt()`
10823 
10824 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10825 @*/
10826 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10827 {
10828   PetscFunctionBegin;
10829   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10830   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10831   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10832 
10833   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10834   PetscFunctionReturn(PETSC_SUCCESS);
10835 }
10836 
10837 /*@
10838   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10839   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10840   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10841   $C_{sp}$ from $C_{den}$.
10842 
10843   Collective
10844 
10845   Input Parameters:
10846 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10847 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10848 
10849   Output Parameter:
10850 . Csp - sparse matrix
10851 
10852   Level: developer
10853 
10854   Note:
10855   These are used internally for some implementations of `MatRARt()`
10856 
10857 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10858 @*/
10859 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10860 {
10861   PetscFunctionBegin;
10862   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10863   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10864   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10865 
10866   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10867   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10868   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10869   PetscFunctionReturn(PETSC_SUCCESS);
10870 }
10871 
10872 /*@
10873   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10874 
10875   Collective
10876 
10877   Input Parameters:
10878 + mat        - the matrix product C
10879 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10880 
10881   Output Parameter:
10882 . color - the new coloring context
10883 
10884   Level: intermediate
10885 
10886 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10887           `MatTransColoringApplyDenToSp()`
10888 @*/
10889 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10890 {
10891   MatTransposeColoring c;
10892   MPI_Comm             comm;
10893 
10894   PetscFunctionBegin;
10895   PetscAssertPointer(color, 3);
10896 
10897   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10898   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10899   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10900   c->ctype = iscoloring->ctype;
10901   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10902   *color = c;
10903   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10904   PetscFunctionReturn(PETSC_SUCCESS);
10905 }
10906 
10907 /*@
10908   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10909   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
10910 
10911   Not Collective
10912 
10913   Input Parameter:
10914 . mat - the matrix
10915 
10916   Output Parameter:
10917 . state - the current state
10918 
10919   Level: intermediate
10920 
10921   Notes:
10922   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10923   different matrices
10924 
10925   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10926 
10927   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10928 
10929 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10930 @*/
10931 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10932 {
10933   PetscFunctionBegin;
10934   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10935   *state = mat->nonzerostate;
10936   PetscFunctionReturn(PETSC_SUCCESS);
10937 }
10938 
10939 /*@
10940   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10941   matrices from each processor
10942 
10943   Collective
10944 
10945   Input Parameters:
10946 + comm   - the communicators the parallel matrix will live on
10947 . seqmat - the input sequential matrices
10948 . n      - number of local columns (or `PETSC_DECIDE`)
10949 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10950 
10951   Output Parameter:
10952 . mpimat - the parallel matrix generated
10953 
10954   Level: developer
10955 
10956   Note:
10957   The number of columns of the matrix in EACH processor MUST be the same.
10958 
10959 .seealso: [](ch_matrices), `Mat`
10960 @*/
10961 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10962 {
10963   PetscMPIInt size;
10964 
10965   PetscFunctionBegin;
10966   PetscCallMPI(MPI_Comm_size(comm, &size));
10967   if (size == 1) {
10968     if (reuse == MAT_INITIAL_MATRIX) {
10969       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10970     } else {
10971       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10972     }
10973     PetscFunctionReturn(PETSC_SUCCESS);
10974   }
10975 
10976   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");
10977 
10978   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10979   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10980   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10981   PetscFunctionReturn(PETSC_SUCCESS);
10982 }
10983 
10984 /*@
10985   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10986 
10987   Collective
10988 
10989   Input Parameters:
10990 + A - the matrix to create subdomains from
10991 - N - requested number of subdomains
10992 
10993   Output Parameters:
10994 + n   - number of subdomains resulting on this MPI process
10995 - iss - `IS` list with indices of subdomains on this MPI process
10996 
10997   Level: advanced
10998 
10999   Note:
11000   The number of subdomains must be smaller than the communicator size
11001 
11002 .seealso: [](ch_matrices), `Mat`, `IS`
11003 @*/
11004 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11005 {
11006   MPI_Comm    comm, subcomm;
11007   PetscMPIInt size, rank, color;
11008   PetscInt    rstart, rend, k;
11009 
11010   PetscFunctionBegin;
11011   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11012   PetscCallMPI(MPI_Comm_size(comm, &size));
11013   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11014   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);
11015   *n    = 1;
11016   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
11017   color = rank / k;
11018   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11019   PetscCall(PetscMalloc1(1, iss));
11020   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11021   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11022   PetscCallMPI(MPI_Comm_free(&subcomm));
11023   PetscFunctionReturn(PETSC_SUCCESS);
11024 }
11025 
11026 /*@
11027   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11028 
11029   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11030   If they are not the same, uses `MatMatMatMult()`.
11031 
11032   Once the coarse grid problem is constructed, correct for interpolation operators
11033   that are not of full rank, which can legitimately happen in the case of non-nested
11034   geometric multigrid.
11035 
11036   Input Parameters:
11037 + restrct     - restriction operator
11038 . dA          - fine grid matrix
11039 . interpolate - interpolation operator
11040 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11041 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11042 
11043   Output Parameter:
11044 . A - the Galerkin coarse matrix
11045 
11046   Options Database Key:
11047 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11048 
11049   Level: developer
11050 
11051   Note:
11052   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11053 
11054 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11055 @*/
11056 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11057 {
11058   IS  zerorows;
11059   Vec diag;
11060 
11061   PetscFunctionBegin;
11062   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11063   /* Construct the coarse grid matrix */
11064   if (interpolate == restrct) {
11065     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11066   } else {
11067     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11068   }
11069 
11070   /* If the interpolation matrix is not of full rank, A will have zero rows.
11071      This can legitimately happen in the case of non-nested geometric multigrid.
11072      In that event, we set the rows of the matrix to the rows of the identity,
11073      ignoring the equations (as the RHS will also be zero). */
11074 
11075   PetscCall(MatFindZeroRows(*A, &zerorows));
11076 
11077   if (zerorows != NULL) { /* if there are any zero rows */
11078     PetscCall(MatCreateVecs(*A, &diag, NULL));
11079     PetscCall(MatGetDiagonal(*A, diag));
11080     PetscCall(VecISSet(diag, zerorows, 1.0));
11081     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11082     PetscCall(VecDestroy(&diag));
11083     PetscCall(ISDestroy(&zerorows));
11084   }
11085   PetscFunctionReturn(PETSC_SUCCESS);
11086 }
11087 
11088 /*@C
11089   MatSetOperation - Allows user to set a matrix operation for any matrix type
11090 
11091   Logically Collective
11092 
11093   Input Parameters:
11094 + mat - the matrix
11095 . op  - the name of the operation
11096 - f   - the function that provides the operation
11097 
11098   Level: developer
11099 
11100   Example Usage:
11101 .vb
11102   extern PetscErrorCode usermult(Mat, Vec, Vec);
11103 
11104   PetscCall(MatCreateXXX(comm, ..., &A));
11105   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11106 .ve
11107 
11108   Notes:
11109   See the file `include/petscmat.h` for a complete list of matrix
11110   operations, which all have the form MATOP_<OPERATION>, where
11111   <OPERATION> is the name (in all capital letters) of the
11112   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11113 
11114   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11115   sequence as the usual matrix interface routines, since they
11116   are intended to be accessed via the usual matrix interface
11117   routines, e.g.,
11118 .vb
11119   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11120 .ve
11121 
11122   In particular each function MUST return `PETSC_SUCCESS` on success and
11123   nonzero on failure.
11124 
11125   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11126 
11127 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11128 @*/
11129 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11130 {
11131   PetscFunctionBegin;
11132   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11133   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11134   (((void (**)(void))mat->ops)[op]) = f;
11135   PetscFunctionReturn(PETSC_SUCCESS);
11136 }
11137 
11138 /*@C
11139   MatGetOperation - Gets a matrix operation for any matrix type.
11140 
11141   Not Collective
11142 
11143   Input Parameters:
11144 + mat - the matrix
11145 - op  - the name of the operation
11146 
11147   Output Parameter:
11148 . f - the function that provides the operation
11149 
11150   Level: developer
11151 
11152   Example Usage:
11153 .vb
11154   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11155 
11156   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11157 .ve
11158 
11159   Notes:
11160   See the file include/petscmat.h for a complete list of matrix
11161   operations, which all have the form MATOP_<OPERATION>, where
11162   <OPERATION> is the name (in all capital letters) of the
11163   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11164 
11165   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11166 
11167 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11168 @*/
11169 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11170 {
11171   PetscFunctionBegin;
11172   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11173   *f = (((void (**)(void))mat->ops)[op]);
11174   PetscFunctionReturn(PETSC_SUCCESS);
11175 }
11176 
11177 /*@
11178   MatHasOperation - Determines whether the given matrix supports the particular operation.
11179 
11180   Not Collective
11181 
11182   Input Parameters:
11183 + mat - the matrix
11184 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11185 
11186   Output Parameter:
11187 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11188 
11189   Level: advanced
11190 
11191   Note:
11192   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11193 
11194 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11195 @*/
11196 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11197 {
11198   PetscFunctionBegin;
11199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11200   PetscAssertPointer(has, 3);
11201   if (mat->ops->hasoperation) {
11202     PetscUseTypeMethod(mat, hasoperation, op, has);
11203   } else {
11204     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11205     else {
11206       *has = PETSC_FALSE;
11207       if (op == MATOP_CREATE_SUBMATRIX) {
11208         PetscMPIInt size;
11209 
11210         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11211         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11212       }
11213     }
11214   }
11215   PetscFunctionReturn(PETSC_SUCCESS);
11216 }
11217 
11218 /*@
11219   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11220 
11221   Collective
11222 
11223   Input Parameter:
11224 . mat - the matrix
11225 
11226   Output Parameter:
11227 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11228 
11229   Level: beginner
11230 
11231 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11232 @*/
11233 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11234 {
11235   PetscFunctionBegin;
11236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11237   PetscValidType(mat, 1);
11238   PetscAssertPointer(cong, 2);
11239   if (!mat->rmap || !mat->cmap) {
11240     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11241     PetscFunctionReturn(PETSC_SUCCESS);
11242   }
11243   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11244     PetscCall(PetscLayoutSetUp(mat->rmap));
11245     PetscCall(PetscLayoutSetUp(mat->cmap));
11246     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11247     if (*cong) mat->congruentlayouts = 1;
11248     else mat->congruentlayouts = 0;
11249   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11250   PetscFunctionReturn(PETSC_SUCCESS);
11251 }
11252 
11253 PetscErrorCode MatSetInf(Mat A)
11254 {
11255   PetscFunctionBegin;
11256   PetscUseTypeMethod(A, setinf);
11257   PetscFunctionReturn(PETSC_SUCCESS);
11258 }
11259 
11260 /*@
11261   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
11262   and possibly removes small values from the graph structure.
11263 
11264   Collective
11265 
11266   Input Parameters:
11267 + A       - the matrix
11268 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11269 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11270 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11271 . num_idx - size of 'index' array
11272 - index   - array of block indices to use for graph strength of connection weight
11273 
11274   Output Parameter:
11275 . graph - the resulting graph
11276 
11277   Level: advanced
11278 
11279 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11280 @*/
11281 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11282 {
11283   PetscFunctionBegin;
11284   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11285   PetscValidType(A, 1);
11286   PetscValidLogicalCollectiveBool(A, scale, 3);
11287   PetscAssertPointer(graph, 7);
11288   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11289   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11290   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11291   PetscFunctionReturn(PETSC_SUCCESS);
11292 }
11293 
11294 /*@
11295   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11296   meaning the same memory is used for the matrix, and no new memory is allocated.
11297 
11298   Collective
11299 
11300   Input Parameters:
11301 + A    - the matrix
11302 - 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
11303 
11304   Level: intermediate
11305 
11306   Developer Note:
11307   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11308   of the arrays in the data structure are unneeded.
11309 
11310 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11311 @*/
11312 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11313 {
11314   PetscFunctionBegin;
11315   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11316   PetscUseTypeMethod(A, eliminatezeros, keep);
11317   PetscFunctionReturn(PETSC_SUCCESS);
11318 }
11319