xref: /petsc/src/mat/interface/matrix.c (revision b44f4de476a10dd52a698c0f9a8f47d015bd1e19)
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 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
882 @*/
883 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
884 {
885   PetscFunctionBegin;
886   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
887   PetscAssertPointer(prefix, 2);
888   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
889   PetscFunctionReturn(PETSC_SUCCESS);
890 }
891 
892 /*@
893   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
894 
895   Not Collective
896 
897   Input Parameter:
898 . A - the matrix
899 
900   Output Parameter:
901 . state - the object state
902 
903   Level: advanced
904 
905   Note:
906   Object state is an integer which gets increased every time
907   the object is changed. By saving and later querying the object state
908   one can determine whether information about the object is still current.
909 
910   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
911 
912 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
913 @*/
914 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
915 {
916   PetscFunctionBegin;
917   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
918   PetscAssertPointer(state, 2);
919   PetscCall(PetscObjectStateGet((PetscObject)A, state));
920   PetscFunctionReturn(PETSC_SUCCESS);
921 }
922 
923 /*@
924   MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()`
925 
926   Collective
927 
928   Input Parameter:
929 . A - the matrix
930 
931   Level: beginner
932 
933   Notes:
934   After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the
935   matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()`
936   makes all of the preallocation space available
937 
938   Current values in the matrix are lost in this call
939 
940   Currently only supported for  `MATAIJ` matrices.
941 
942 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
943 @*/
944 PetscErrorCode MatResetPreallocation(Mat A)
945 {
946   PetscFunctionBegin;
947   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
948   PetscValidType(A, 1);
949   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
950   PetscFunctionReturn(PETSC_SUCCESS);
951 }
952 
953 /*@
954   MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`.
955 
956   Collective
957 
958   Input Parameter:
959 . A - the matrix
960 
961   Level: intermediate
962 
963   Notes:
964   The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
965 
966   Currently only supported for `MATAIJ` matrices.
967 
968 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()`
969 @*/
970 PetscErrorCode MatResetHash(Mat A)
971 {
972   PetscFunctionBegin;
973   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
974   PetscValidType(A, 1);
975   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()");
976   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
977   PetscUseMethod(A, "MatResetHash_C", (Mat), (A));
978   /* These flags are used to determine whether certain setups occur */
979   A->was_assembled = PETSC_FALSE;
980   A->assembled     = PETSC_FALSE;
981   /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */
982   PetscCall(PetscObjectStateIncrease((PetscObject)A));
983   PetscFunctionReturn(PETSC_SUCCESS);
984 }
985 
986 /*@
987   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
988 
989   Collective
990 
991   Input Parameter:
992 . A - the matrix
993 
994   Level: advanced
995 
996   Notes:
997   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
998   setting values in the matrix.
999 
1000   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
1001 
1002 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
1003 @*/
1004 PetscErrorCode MatSetUp(Mat A)
1005 {
1006   PetscFunctionBegin;
1007   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1008   if (!((PetscObject)A)->type_name) {
1009     PetscMPIInt size;
1010 
1011     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1012     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
1013   }
1014   if (!A->preallocated) PetscTryTypeMethod(A, setup);
1015   PetscCall(PetscLayoutSetUp(A->rmap));
1016   PetscCall(PetscLayoutSetUp(A->cmap));
1017   A->preallocated = PETSC_TRUE;
1018   PetscFunctionReturn(PETSC_SUCCESS);
1019 }
1020 
1021 #if defined(PETSC_HAVE_SAWS)
1022   #include <petscviewersaws.h>
1023 #endif
1024 
1025 /*
1026    If threadsafety is on extraneous matrices may be printed
1027 
1028    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
1029 */
1030 #if !defined(PETSC_HAVE_THREADSAFETY)
1031 static PetscInt insidematview = 0;
1032 #endif
1033 
1034 /*@
1035   MatViewFromOptions - View properties of the matrix based on options set in the options database
1036 
1037   Collective
1038 
1039   Input Parameters:
1040 + A    - the matrix
1041 . obj  - optional additional object that provides the options prefix to use
1042 - name - command line option
1043 
1044   Options Database Key:
1045 . -mat_view [viewertype]:... - the viewer and its options
1046 
1047   Level: intermediate
1048 
1049   Note:
1050 .vb
1051     If no value is provided ascii:stdout is used
1052        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1053                                                   for example ascii::ascii_info prints just the information about the object not all details
1054                                                   unless :append is given filename opens in write mode, overwriting what was already there
1055        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1056        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1057        socket[:port]                             defaults to the standard output port
1058        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1059 .ve
1060 
1061 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1062 @*/
1063 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1064 {
1065   PetscFunctionBegin;
1066   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1067 #if !defined(PETSC_HAVE_THREADSAFETY)
1068   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1069 #endif
1070   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1071   PetscFunctionReturn(PETSC_SUCCESS);
1072 }
1073 
1074 /*@
1075   MatView - display information about a matrix in a variety ways
1076 
1077   Collective on viewer
1078 
1079   Input Parameters:
1080 + mat    - the matrix
1081 - viewer - visualization context
1082 
1083   Options Database Keys:
1084 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1085 . -mat_view ::ascii_info_detail    - Prints more detailed info
1086 . -mat_view                        - Prints matrix in ASCII format
1087 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1088 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1089 . -display <name>                  - Sets display name (default is host)
1090 . -draw_pause <sec>                - Sets number of seconds to pause after display
1091 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1092 . -viewer_socket_machine <machine> - -
1093 . -viewer_socket_port <port>       - -
1094 . -mat_view binary                 - save matrix to file in binary format
1095 - -viewer_binary_filename <name>   - -
1096 
1097   Level: beginner
1098 
1099   Notes:
1100   The available visualization contexts include
1101 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1102 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1103 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1104 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1105 
1106   The user can open alternative visualization contexts with
1107 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1108 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1109 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1110 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1111 
1112   The user can call `PetscViewerPushFormat()` to specify the output
1113   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1114   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1115 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1116 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1117 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1118 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1119 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1120 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1121 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1122 
1123   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1124   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1125 
1126   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1127 
1128   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1129   viewer is used.
1130 
1131   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1132   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1133 
1134   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1135   and then use the following mouse functions.
1136 .vb
1137   left mouse: zoom in
1138   middle mouse: zoom out
1139   right mouse: continue with the simulation
1140 .ve
1141 
1142 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1143           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1144 @*/
1145 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1146 {
1147   PetscInt          rows, cols, rbs, cbs;
1148   PetscBool         isascii, isstring, issaws;
1149   PetscViewerFormat format;
1150   PetscMPIInt       size;
1151 
1152   PetscFunctionBegin;
1153   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1154   PetscValidType(mat, 1);
1155   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1156   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1157 
1158   PetscCall(PetscViewerGetFormat(viewer, &format));
1159   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1160   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1161 
1162 #if !defined(PETSC_HAVE_THREADSAFETY)
1163   insidematview++;
1164 #endif
1165   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1166   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1167   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1168   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");
1169 
1170   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1171   if (isascii) {
1172     if (!mat->preallocated) {
1173       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1174 #if !defined(PETSC_HAVE_THREADSAFETY)
1175       insidematview--;
1176 #endif
1177       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1178       PetscFunctionReturn(PETSC_SUCCESS);
1179     }
1180     if (!mat->assembled) {
1181       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1182 #if !defined(PETSC_HAVE_THREADSAFETY)
1183       insidematview--;
1184 #endif
1185       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1186       PetscFunctionReturn(PETSC_SUCCESS);
1187     }
1188     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1189     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1190       MatNullSpace nullsp, transnullsp;
1191 
1192       PetscCall(PetscViewerASCIIPushTab(viewer));
1193       PetscCall(MatGetSize(mat, &rows, &cols));
1194       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1195       if (rbs != 1 || cbs != 1) {
1196         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" : ""));
1197         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1198       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1199       if (mat->factortype) {
1200         MatSolverType solver;
1201         PetscCall(MatFactorGetSolverType(mat, &solver));
1202         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1203       }
1204       if (mat->ops->getinfo) {
1205         MatInfo info;
1206         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1207         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1208         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1209       }
1210       PetscCall(MatGetNullSpace(mat, &nullsp));
1211       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1212       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1213       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1214       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1215       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1216       PetscCall(PetscViewerASCIIPushTab(viewer));
1217       PetscCall(MatProductView(mat, viewer));
1218       PetscCall(PetscViewerASCIIPopTab(viewer));
1219       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1220         IS tmp;
1221 
1222         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1223         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1224         PetscCall(PetscViewerASCIIPushTab(viewer));
1225         PetscCall(ISView(tmp, viewer));
1226         PetscCall(PetscViewerASCIIPopTab(viewer));
1227         PetscCall(ISDestroy(&tmp));
1228       }
1229     }
1230   } else if (issaws) {
1231 #if defined(PETSC_HAVE_SAWS)
1232     PetscMPIInt rank;
1233 
1234     PetscCall(PetscObjectName((PetscObject)mat));
1235     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1236     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1237 #endif
1238   } else if (isstring) {
1239     const char *type;
1240     PetscCall(MatGetType(mat, &type));
1241     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1242     PetscTryTypeMethod(mat, view, viewer);
1243   }
1244   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1245     PetscCall(PetscViewerASCIIPushTab(viewer));
1246     PetscUseTypeMethod(mat, viewnative, viewer);
1247     PetscCall(PetscViewerASCIIPopTab(viewer));
1248   } else if (mat->ops->view) {
1249     PetscCall(PetscViewerASCIIPushTab(viewer));
1250     PetscUseTypeMethod(mat, view, viewer);
1251     PetscCall(PetscViewerASCIIPopTab(viewer));
1252   }
1253   if (isascii) {
1254     PetscCall(PetscViewerGetFormat(viewer, &format));
1255     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1256   }
1257   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1258 #if !defined(PETSC_HAVE_THREADSAFETY)
1259   insidematview--;
1260 #endif
1261   PetscFunctionReturn(PETSC_SUCCESS);
1262 }
1263 
1264 #if defined(PETSC_USE_DEBUG)
1265   #include <../src/sys/totalview/tv_data_display.h>
1266 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1267 {
1268   TV_add_row("Local rows", "int", &mat->rmap->n);
1269   TV_add_row("Local columns", "int", &mat->cmap->n);
1270   TV_add_row("Global rows", "int", &mat->rmap->N);
1271   TV_add_row("Global columns", "int", &mat->cmap->N);
1272   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1273   return TV_format_OK;
1274 }
1275 #endif
1276 
1277 /*@
1278   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1279   with `MatView()`.  The matrix format is determined from the options database.
1280   Generates a parallel MPI matrix if the communicator has more than one
1281   processor.  The default matrix type is `MATAIJ`.
1282 
1283   Collective
1284 
1285   Input Parameters:
1286 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1287             or some related function before a call to `MatLoad()`
1288 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1289 
1290   Options Database Key:
1291 . -matload_block_size <bs> - set block size
1292 
1293   Level: beginner
1294 
1295   Notes:
1296   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1297   `Mat` before calling this routine if you wish to set it from the options database.
1298 
1299   `MatLoad()` automatically loads into the options database any options
1300   given in the file filename.info where filename is the name of the file
1301   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1302   file will be ignored if you use the -viewer_binary_skip_info option.
1303 
1304   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1305   sets the default matrix type AIJ and sets the local and global sizes.
1306   If type and/or size is already set, then the same are used.
1307 
1308   In parallel, each processor can load a subset of rows (or the
1309   entire matrix).  This routine is especially useful when a large
1310   matrix is stored on disk and only part of it is desired on each
1311   processor.  For example, a parallel solver may access only some of
1312   the rows from each processor.  The algorithm used here reads
1313   relatively small blocks of data rather than reading the entire
1314   matrix and then subsetting it.
1315 
1316   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1317   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1318   or the sequence like
1319 .vb
1320     `PetscViewer` v;
1321     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1322     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1323     `PetscViewerSetFromOptions`(v);
1324     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1325     `PetscViewerFileSetName`(v,"datafile");
1326 .ve
1327   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1328 .vb
1329   -viewer_type {binary, hdf5}
1330 .ve
1331 
1332   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1333   and src/mat/tutorials/ex10.c with the second approach.
1334 
1335   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1336   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1337   Multiple objects, both matrices and vectors, can be stored within the same file.
1338   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1339 
1340   Most users should not need to know the details of the binary storage
1341   format, since `MatLoad()` and `MatView()` completely hide these details.
1342   But for anyone who is interested, the standard binary matrix storage
1343   format is
1344 
1345 .vb
1346     PetscInt    MAT_FILE_CLASSID
1347     PetscInt    number of rows
1348     PetscInt    number of columns
1349     PetscInt    total number of nonzeros
1350     PetscInt    *number nonzeros in each row
1351     PetscInt    *column indices of all nonzeros (starting index is zero)
1352     PetscScalar *values of all nonzeros
1353 .ve
1354   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1355   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
1356   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1357 
1358   PETSc automatically does the byte swapping for
1359   machines that store the bytes reversed. Thus if you write your own binary
1360   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1361   and `PetscBinaryWrite()` to see how this may be done.
1362 
1363   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1364   Each processor's chunk is loaded independently by its owning MPI process.
1365   Multiple objects, both matrices and vectors, can be stored within the same file.
1366   They are looked up by their PetscObject name.
1367 
1368   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1369   by default the same structure and naming of the AIJ arrays and column count
1370   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1371 .vb
1372   save example.mat A b -v7.3
1373 .ve
1374   can be directly read by this routine (see Reference 1 for details).
1375 
1376   Depending on your MATLAB version, this format might be a default,
1377   otherwise you can set it as default in Preferences.
1378 
1379   Unless -nocompression flag is used to save the file in MATLAB,
1380   PETSc must be configured with ZLIB package.
1381 
1382   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1383 
1384   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1385 
1386   Corresponding `MatView()` is not yet implemented.
1387 
1388   The loaded matrix is actually a transpose of the original one in MATLAB,
1389   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1390   With this format, matrix is automatically transposed by PETSc,
1391   unless the matrix is marked as SPD or symmetric
1392   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1393 
1394   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1395 
1396 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1397  @*/
1398 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1399 {
1400   PetscBool flg;
1401 
1402   PetscFunctionBegin;
1403   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1404   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1405 
1406   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1407 
1408   flg = PETSC_FALSE;
1409   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1410   if (flg) {
1411     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1412     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1413   }
1414   flg = PETSC_FALSE;
1415   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1416   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1417 
1418   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1419   PetscUseTypeMethod(mat, load, viewer);
1420   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1421   PetscFunctionReturn(PETSC_SUCCESS);
1422 }
1423 
1424 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1425 {
1426   Mat_Redundant *redund = *redundant;
1427 
1428   PetscFunctionBegin;
1429   if (redund) {
1430     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1431       PetscCall(ISDestroy(&redund->isrow));
1432       PetscCall(ISDestroy(&redund->iscol));
1433       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1434     } else {
1435       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1436       PetscCall(PetscFree(redund->sbuf_j));
1437       PetscCall(PetscFree(redund->sbuf_a));
1438       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1439         PetscCall(PetscFree(redund->rbuf_j[i]));
1440         PetscCall(PetscFree(redund->rbuf_a[i]));
1441       }
1442       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1443     }
1444 
1445     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1446     PetscCall(PetscFree(redund));
1447   }
1448   PetscFunctionReturn(PETSC_SUCCESS);
1449 }
1450 
1451 /*@
1452   MatDestroy - Frees space taken by a matrix.
1453 
1454   Collective
1455 
1456   Input Parameter:
1457 . A - the matrix
1458 
1459   Level: beginner
1460 
1461   Developer Note:
1462   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1463   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1464   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1465   if changes are needed here.
1466 
1467 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1468 @*/
1469 PetscErrorCode MatDestroy(Mat *A)
1470 {
1471   PetscFunctionBegin;
1472   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1473   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1474   if (--((PetscObject)*A)->refct > 0) {
1475     *A = NULL;
1476     PetscFunctionReturn(PETSC_SUCCESS);
1477   }
1478 
1479   /* if memory was published with SAWs then destroy it */
1480   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1481   PetscTryTypeMethod(*A, destroy);
1482 
1483   PetscCall(PetscFree((*A)->factorprefix));
1484   PetscCall(PetscFree((*A)->defaultvectype));
1485   PetscCall(PetscFree((*A)->defaultrandtype));
1486   PetscCall(PetscFree((*A)->bsizes));
1487   PetscCall(PetscFree((*A)->solvertype));
1488   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1489   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1490   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1491   PetscCall(MatProductClear(*A));
1492   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1493   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1494   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1495   PetscCall(MatDestroy(&(*A)->schur));
1496   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1497   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1498   PetscCall(PetscHeaderDestroy(A));
1499   PetscFunctionReturn(PETSC_SUCCESS);
1500 }
1501 
1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1503 /*@
1504   MatSetValues - Inserts or adds a block of values into a matrix.
1505   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1506   MUST be called after all calls to `MatSetValues()` have been completed.
1507 
1508   Not Collective
1509 
1510   Input Parameters:
1511 + mat  - the matrix
1512 . v    - a logically two-dimensional array of values
1513 . m    - the number of rows
1514 . idxm - the global indices of the rows
1515 . n    - the number of columns
1516 . idxn - the global indices of the columns
1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519   Level: beginner
1520 
1521   Notes:
1522   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1523 
1524   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525   options cannot be mixed without intervening calls to the assembly
1526   routines.
1527 
1528   `MatSetValues()` uses 0-based row and column numbers in Fortran
1529   as well as in C.
1530 
1531   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1532   simply ignored. This allows easily inserting element stiffness matrices
1533   with homogeneous Dirichlet boundary conditions that you don't want represented
1534   in the matrix.
1535 
1536   Efficiency Alert:
1537   The routine `MatSetValuesBlocked()` may offer much better efficiency
1538   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540   Fortran Notes:
1541   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1542 .vb
1543   call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr)
1544 .ve
1545 
1546   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1547 
1548   Developer Note:
1549   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1550   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1551 
1552 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1553           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1554 @*/
1555 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1556 {
1557   PetscFunctionBeginHot;
1558   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1559   PetscValidType(mat, 1);
1560   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1561   PetscAssertPointer(idxm, 3);
1562   PetscAssertPointer(idxn, 5);
1563   MatCheckPreallocated(mat, 1);
1564 
1565   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1566   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1567 
1568   if (PetscDefined(USE_DEBUG)) {
1569     PetscInt i, j;
1570 
1571     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1572     if (v) {
1573       for (i = 0; i < m; i++) {
1574         for (j = 0; j < n; j++) {
1575           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1576 #if defined(PETSC_USE_COMPLEX)
1577             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]);
1578 #else
1579             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]);
1580 #endif
1581         }
1582       }
1583     }
1584     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);
1585     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);
1586   }
1587 
1588   if (mat->assembled) {
1589     mat->was_assembled = PETSC_TRUE;
1590     mat->assembled     = PETSC_FALSE;
1591   }
1592   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1593   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1594   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1595   PetscFunctionReturn(PETSC_SUCCESS);
1596 }
1597 
1598 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1599 /*@
1600   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1601   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1602   MUST be called after all calls to `MatSetValues()` have been completed.
1603 
1604   Not Collective
1605 
1606   Input Parameters:
1607 + mat  - the matrix
1608 . v    - a logically two-dimensional array of values
1609 . ism  - the rows to provide
1610 . isn  - the columns to provide
1611 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1612 
1613   Level: beginner
1614 
1615   Notes:
1616   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1617 
1618   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1619   options cannot be mixed without intervening calls to the assembly
1620   routines.
1621 
1622   `MatSetValues()` uses 0-based row and column numbers in Fortran
1623   as well as in C.
1624 
1625   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1626   simply ignored. This allows easily inserting element stiffness matrices
1627   with homogeneous Dirichlet boundary conditions that you don't want represented
1628   in the matrix.
1629 
1630   Efficiency Alert:
1631   The routine `MatSetValuesBlocked()` may offer much better efficiency
1632   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1633 
1634   This is currently not optimized for any particular `ISType`
1635 
1636   Developer Note:
1637   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1638   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1639 
1640 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1641           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1642 @*/
1643 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1644 {
1645   PetscInt        m, n;
1646   const PetscInt *rows, *cols;
1647 
1648   PetscFunctionBeginHot;
1649   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1650   PetscCall(ISGetIndices(ism, &rows));
1651   PetscCall(ISGetIndices(isn, &cols));
1652   PetscCall(ISGetLocalSize(ism, &m));
1653   PetscCall(ISGetLocalSize(isn, &n));
1654   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1655   PetscCall(ISRestoreIndices(ism, &rows));
1656   PetscCall(ISRestoreIndices(isn, &cols));
1657   PetscFunctionReturn(PETSC_SUCCESS);
1658 }
1659 
1660 /*@
1661   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1662   values into a matrix
1663 
1664   Not Collective
1665 
1666   Input Parameters:
1667 + mat - the matrix
1668 . row - the (block) row to set
1669 - v   - a logically two-dimensional array of values
1670 
1671   Level: intermediate
1672 
1673   Notes:
1674   The values, `v`, are column-oriented (for the block version) and sorted
1675 
1676   All the nonzero values in `row` must be provided
1677 
1678   The matrix must have previously had its column indices set, likely by having been assembled.
1679 
1680   `row` must belong to this MPI process
1681 
1682 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1683           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1684 @*/
1685 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1686 {
1687   PetscInt globalrow;
1688 
1689   PetscFunctionBegin;
1690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1691   PetscValidType(mat, 1);
1692   PetscAssertPointer(v, 3);
1693   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1694   PetscCall(MatSetValuesRow(mat, globalrow, v));
1695   PetscFunctionReturn(PETSC_SUCCESS);
1696 }
1697 
1698 /*@
1699   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1700   values into a matrix
1701 
1702   Not Collective
1703 
1704   Input Parameters:
1705 + mat - the matrix
1706 . row - the (block) row to set
1707 - 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
1708 
1709   Level: advanced
1710 
1711   Notes:
1712   The values, `v`, are column-oriented for the block version.
1713 
1714   All the nonzeros in `row` must be provided
1715 
1716   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1717 
1718   `row` must belong to this process
1719 
1720 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1721           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1722 @*/
1723 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1724 {
1725   PetscFunctionBeginHot;
1726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1727   PetscValidType(mat, 1);
1728   MatCheckPreallocated(mat, 1);
1729   PetscAssertPointer(v, 3);
1730   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1731   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1732   mat->insertmode = INSERT_VALUES;
1733 
1734   if (mat->assembled) {
1735     mat->was_assembled = PETSC_TRUE;
1736     mat->assembled     = PETSC_FALSE;
1737   }
1738   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1739   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1740   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1741   PetscFunctionReturn(PETSC_SUCCESS);
1742 }
1743 
1744 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1745 /*@
1746   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1747   Using structured grid indexing
1748 
1749   Not Collective
1750 
1751   Input Parameters:
1752 + mat  - the matrix
1753 . m    - number of rows being entered
1754 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1755 . n    - number of columns being entered
1756 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1757 . v    - a logically two-dimensional array of values
1758 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1759 
1760   Level: beginner
1761 
1762   Notes:
1763   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1764 
1765   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1766   options cannot be mixed without intervening calls to the assembly
1767   routines.
1768 
1769   The grid coordinates are across the entire grid, not just the local portion
1770 
1771   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1772   as well as in C.
1773 
1774   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1775 
1776   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1777   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1778 
1779   The columns and rows in the stencil passed in MUST be contained within the
1780   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1781   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1782   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1783   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1784 
1785   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1786   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1787   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1788   `DM_BOUNDARY_PERIODIC` boundary type.
1789 
1790   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
1791   a single value per point) you can skip filling those indices.
1792 
1793   Inspired by the structured grid interface to the HYPRE package
1794   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1795 
1796   Efficiency Alert:
1797   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1798   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1799 
1800 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1801           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1802 @*/
1803 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1804 {
1805   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1806   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1807   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1808 
1809   PetscFunctionBegin;
1810   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1811   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1812   PetscValidType(mat, 1);
1813   PetscAssertPointer(idxm, 3);
1814   PetscAssertPointer(idxn, 5);
1815 
1816   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1817     jdxm = buf;
1818     jdxn = buf + m;
1819   } else {
1820     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1821     jdxm = bufm;
1822     jdxn = bufn;
1823   }
1824   for (i = 0; i < m; i++) {
1825     for (j = 0; j < 3 - sdim; j++) dxm++;
1826     tmp = *dxm++ - starts[0];
1827     for (j = 0; j < dim - 1; j++) {
1828       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1829       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1830     }
1831     if (mat->stencil.noc) dxm++;
1832     jdxm[i] = tmp;
1833   }
1834   for (i = 0; i < n; i++) {
1835     for (j = 0; j < 3 - sdim; j++) dxn++;
1836     tmp = *dxn++ - starts[0];
1837     for (j = 0; j < dim - 1; j++) {
1838       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1839       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1840     }
1841     if (mat->stencil.noc) dxn++;
1842     jdxn[i] = tmp;
1843   }
1844   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1845   PetscCall(PetscFree2(bufm, bufn));
1846   PetscFunctionReturn(PETSC_SUCCESS);
1847 }
1848 
1849 /*@
1850   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1851   Using structured grid indexing
1852 
1853   Not Collective
1854 
1855   Input Parameters:
1856 + mat  - the matrix
1857 . m    - number of rows being entered
1858 . idxm - grid coordinates for matrix rows being entered
1859 . n    - number of columns being entered
1860 . idxn - grid coordinates for matrix columns being entered
1861 . v    - a logically two-dimensional array of values
1862 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1863 
1864   Level: beginner
1865 
1866   Notes:
1867   By default the values, `v`, are row-oriented and unsorted.
1868   See `MatSetOption()` for other options.
1869 
1870   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1871   options cannot be mixed without intervening calls to the assembly
1872   routines.
1873 
1874   The grid coordinates are across the entire grid, not just the local portion
1875 
1876   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1877   as well as in C.
1878 
1879   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1880 
1881   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1882   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1883 
1884   The columns and rows in the stencil passed in MUST be contained within the
1885   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1886   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1887   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1888   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1889 
1890   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1891   simply ignored. This allows easily inserting element stiffness matrices
1892   with homogeneous Dirichlet boundary conditions that you don't want represented
1893   in the matrix.
1894 
1895   Inspired by the structured grid interface to the HYPRE package
1896   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1897 
1898   Fortran Note:
1899   `idxm` and `idxn` should be declared as
1900 .vb
1901     MatStencil idxm(4,m),idxn(4,n)
1902 .ve
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 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2467           `MatGetValuesLocal()`
2468 @*/
2469 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2470 {
2471   PetscFunctionBeginHot;
2472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2473   PetscValidType(mat, 1);
2474   MatCheckPreallocated(mat, 1);
2475   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2476   PetscAssertPointer(irow, 3);
2477   PetscAssertPointer(icol, 5);
2478   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2479   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2480   if (PetscDefined(USE_DEBUG)) {
2481     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2482     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2483   }
2484 
2485   if (mat->assembled) {
2486     mat->was_assembled = PETSC_TRUE;
2487     mat->assembled     = PETSC_FALSE;
2488   }
2489   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2490   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2491   else {
2492     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2493     const PetscInt *irowm, *icolm;
2494 
2495     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2496       bufr  = buf;
2497       bufc  = buf + nrow;
2498       irowm = bufr;
2499       icolm = bufc;
2500     } else {
2501       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2502       irowm = bufr;
2503       icolm = bufc;
2504     }
2505     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2506     else irowm = irow;
2507     if (mat->cmap->mapping) {
2508       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2509         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2510       } else icolm = irowm;
2511     } else icolm = icol;
2512     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2513     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2514   }
2515   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2516   PetscFunctionReturn(PETSC_SUCCESS);
2517 }
2518 
2519 /*@
2520   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2521   using a local ordering of the nodes a block at a time.
2522 
2523   Not Collective
2524 
2525   Input Parameters:
2526 + mat  - the matrix
2527 . nrow - number of rows
2528 . irow - the row local indices
2529 . ncol - number of columns
2530 . icol - the column local indices
2531 . y    - a logically two-dimensional array of values
2532 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2533 
2534   Level: intermediate
2535 
2536   Notes:
2537   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2538   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2539 
2540   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2541   options cannot be mixed without intervening calls to the assembly
2542   routines.
2543 
2544   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2545   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2546 
2547   Fortran Notes:
2548   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2549 .vb
2550   call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr)
2551 .ve
2552 
2553   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2554 
2555 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2556           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2557 @*/
2558 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2559 {
2560   PetscFunctionBeginHot;
2561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2562   PetscValidType(mat, 1);
2563   MatCheckPreallocated(mat, 1);
2564   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2565   PetscAssertPointer(irow, 3);
2566   PetscAssertPointer(icol, 5);
2567   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2568   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2569   if (PetscDefined(USE_DEBUG)) {
2570     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2571     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);
2572   }
2573 
2574   if (mat->assembled) {
2575     mat->was_assembled = PETSC_TRUE;
2576     mat->assembled     = PETSC_FALSE;
2577   }
2578   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2579     PetscInt irbs, rbs;
2580     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2581     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2582     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2583   }
2584   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2585     PetscInt icbs, cbs;
2586     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2587     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2588     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2589   }
2590   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2591   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2592   else {
2593     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2594     const PetscInt *irowm, *icolm;
2595 
2596     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2597       bufr  = buf;
2598       bufc  = buf + nrow;
2599       irowm = bufr;
2600       icolm = bufc;
2601     } else {
2602       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2603       irowm = bufr;
2604       icolm = bufc;
2605     }
2606     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2607     else irowm = irow;
2608     if (mat->cmap->mapping) {
2609       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2610         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2611       } else icolm = irowm;
2612     } else icolm = icol;
2613     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2614     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2615   }
2616   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2617   PetscFunctionReturn(PETSC_SUCCESS);
2618 }
2619 
2620 /*@
2621   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2622 
2623   Collective
2624 
2625   Input Parameters:
2626 + mat - the matrix
2627 - x   - the vector to be multiplied
2628 
2629   Output Parameter:
2630 . y - the result
2631 
2632   Level: developer
2633 
2634   Note:
2635   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2636   call `MatMultDiagonalBlock`(A,y,y).
2637 
2638 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2639 @*/
2640 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2641 {
2642   PetscFunctionBegin;
2643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2644   PetscValidType(mat, 1);
2645   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2646   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2647 
2648   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2649   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2650   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2651   MatCheckPreallocated(mat, 1);
2652 
2653   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2654   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2655   PetscFunctionReturn(PETSC_SUCCESS);
2656 }
2657 
2658 /*@
2659   MatMult - Computes the matrix-vector product, $y = Ax$.
2660 
2661   Neighbor-wise Collective
2662 
2663   Input Parameters:
2664 + mat - the matrix
2665 - x   - the vector to be multiplied
2666 
2667   Output Parameter:
2668 . y - the result
2669 
2670   Level: beginner
2671 
2672   Note:
2673   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2674   call `MatMult`(A,y,y).
2675 
2676 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2677 @*/
2678 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2679 {
2680   PetscFunctionBegin;
2681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2682   PetscValidType(mat, 1);
2683   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2684   VecCheckAssembled(x);
2685   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2686   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2687   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2688   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2689   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);
2690   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);
2691   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);
2692   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);
2693   PetscCall(VecSetErrorIfLocked(y, 3));
2694   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2695   MatCheckPreallocated(mat, 1);
2696 
2697   PetscCall(VecLockReadPush(x));
2698   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2699   PetscUseTypeMethod(mat, mult, x, y);
2700   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2701   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2702   PetscCall(VecLockReadPop(x));
2703   PetscFunctionReturn(PETSC_SUCCESS);
2704 }
2705 
2706 /*@
2707   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2708 
2709   Neighbor-wise Collective
2710 
2711   Input Parameters:
2712 + mat - the matrix
2713 - x   - the vector to be multiplied
2714 
2715   Output Parameter:
2716 . y - the result
2717 
2718   Level: beginner
2719 
2720   Notes:
2721   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2722   call `MatMultTranspose`(A,y,y).
2723 
2724   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2725   use `MatMultHermitianTranspose()`
2726 
2727 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2728 @*/
2729 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2730 {
2731   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2732 
2733   PetscFunctionBegin;
2734   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2735   PetscValidType(mat, 1);
2736   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2737   VecCheckAssembled(x);
2738   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2739 
2740   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2741   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2742   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2743   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);
2744   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);
2745   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);
2746   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);
2747   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2748   MatCheckPreallocated(mat, 1);
2749 
2750   if (!mat->ops->multtranspose) {
2751     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2752     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);
2753   } else op = mat->ops->multtranspose;
2754   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2755   PetscCall(VecLockReadPush(x));
2756   PetscCall((*op)(mat, x, y));
2757   PetscCall(VecLockReadPop(x));
2758   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2759   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2760   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2761   PetscFunctionReturn(PETSC_SUCCESS);
2762 }
2763 
2764 /*@
2765   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2766 
2767   Neighbor-wise Collective
2768 
2769   Input Parameters:
2770 + mat - the matrix
2771 - x   - the vector to be multiplied
2772 
2773   Output Parameter:
2774 . y - the result
2775 
2776   Level: beginner
2777 
2778   Notes:
2779   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2780   call `MatMultHermitianTranspose`(A,y,y).
2781 
2782   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2783 
2784   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2785 
2786 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2787 @*/
2788 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2789 {
2790   PetscFunctionBegin;
2791   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2792   PetscValidType(mat, 1);
2793   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2794   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2795 
2796   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2797   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2798   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2799   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);
2800   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);
2801   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);
2802   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);
2803   MatCheckPreallocated(mat, 1);
2804 
2805   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2806 #if defined(PETSC_USE_COMPLEX)
2807   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2808     PetscCall(VecLockReadPush(x));
2809     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2810     else PetscUseTypeMethod(mat, mult, x, y);
2811     PetscCall(VecLockReadPop(x));
2812   } else {
2813     Vec w;
2814     PetscCall(VecDuplicate(x, &w));
2815     PetscCall(VecCopy(x, w));
2816     PetscCall(VecConjugate(w));
2817     PetscCall(MatMultTranspose(mat, w, y));
2818     PetscCall(VecDestroy(&w));
2819     PetscCall(VecConjugate(y));
2820   }
2821   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2822 #else
2823   PetscCall(MatMultTranspose(mat, x, y));
2824 #endif
2825   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2826   PetscFunctionReturn(PETSC_SUCCESS);
2827 }
2828 
2829 /*@
2830   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2831 
2832   Neighbor-wise Collective
2833 
2834   Input Parameters:
2835 + mat - the matrix
2836 . v1  - the vector to be multiplied by `mat`
2837 - v2  - the vector to be added to the result
2838 
2839   Output Parameter:
2840 . v3 - the result
2841 
2842   Level: beginner
2843 
2844   Note:
2845   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2846   call `MatMultAdd`(A,v1,v2,v1).
2847 
2848 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2849 @*/
2850 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2851 {
2852   PetscFunctionBegin;
2853   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2854   PetscValidType(mat, 1);
2855   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2856   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2857   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2858 
2859   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2860   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2861   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);
2862   /* 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);
2863      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); */
2864   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);
2865   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);
2866   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2867   MatCheckPreallocated(mat, 1);
2868 
2869   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2870   PetscCall(VecLockReadPush(v1));
2871   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2872   PetscCall(VecLockReadPop(v1));
2873   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2874   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2875   PetscFunctionReturn(PETSC_SUCCESS);
2876 }
2877 
2878 /*@
2879   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2880 
2881   Neighbor-wise Collective
2882 
2883   Input Parameters:
2884 + mat - the matrix
2885 . v1  - the vector to be multiplied by the transpose of the matrix
2886 - v2  - the vector to be added to the result
2887 
2888   Output Parameter:
2889 . v3 - the result
2890 
2891   Level: beginner
2892 
2893   Note:
2894   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2895   call `MatMultTransposeAdd`(A,v1,v2,v1).
2896 
2897 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2898 @*/
2899 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2900 {
2901   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2902 
2903   PetscFunctionBegin;
2904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2905   PetscValidType(mat, 1);
2906   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2907   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2908   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2909 
2910   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2911   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2912   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);
2913   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);
2914   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);
2915   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2916   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2917   MatCheckPreallocated(mat, 1);
2918 
2919   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2920   PetscCall(VecLockReadPush(v1));
2921   PetscCall((*op)(mat, v1, v2, v3));
2922   PetscCall(VecLockReadPop(v1));
2923   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2924   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2925   PetscFunctionReturn(PETSC_SUCCESS);
2926 }
2927 
2928 /*@
2929   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2930 
2931   Neighbor-wise Collective
2932 
2933   Input Parameters:
2934 + mat - the matrix
2935 . v1  - the vector to be multiplied by the Hermitian transpose
2936 - v2  - the vector to be added to the result
2937 
2938   Output Parameter:
2939 . v3 - the result
2940 
2941   Level: beginner
2942 
2943   Note:
2944   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2945   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2946 
2947 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2948 @*/
2949 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2950 {
2951   PetscFunctionBegin;
2952   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2953   PetscValidType(mat, 1);
2954   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2955   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2956   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2957 
2958   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2959   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2960   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2961   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);
2962   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);
2963   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);
2964   MatCheckPreallocated(mat, 1);
2965 
2966   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2967   PetscCall(VecLockReadPush(v1));
2968   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2969   else {
2970     Vec w, z;
2971     PetscCall(VecDuplicate(v1, &w));
2972     PetscCall(VecCopy(v1, w));
2973     PetscCall(VecConjugate(w));
2974     PetscCall(VecDuplicate(v3, &z));
2975     PetscCall(MatMultTranspose(mat, w, z));
2976     PetscCall(VecDestroy(&w));
2977     PetscCall(VecConjugate(z));
2978     if (v2 != v3) {
2979       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2980     } else {
2981       PetscCall(VecAXPY(v3, 1.0, z));
2982     }
2983     PetscCall(VecDestroy(&z));
2984   }
2985   PetscCall(VecLockReadPop(v1));
2986   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2987   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2988   PetscFunctionReturn(PETSC_SUCCESS);
2989 }
2990 
2991 /*@
2992   MatGetFactorType - gets the type of factorization a matrix is
2993 
2994   Not Collective
2995 
2996   Input Parameter:
2997 . mat - the matrix
2998 
2999   Output Parameter:
3000 . 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`
3001 
3002   Level: intermediate
3003 
3004 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3005           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3006 @*/
3007 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
3008 {
3009   PetscFunctionBegin;
3010   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3011   PetscValidType(mat, 1);
3012   PetscAssertPointer(t, 2);
3013   *t = mat->factortype;
3014   PetscFunctionReturn(PETSC_SUCCESS);
3015 }
3016 
3017 /*@
3018   MatSetFactorType - sets the type of factorization a matrix is
3019 
3020   Logically Collective
3021 
3022   Input Parameters:
3023 + mat - the matrix
3024 - t   - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3025 
3026   Level: intermediate
3027 
3028 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
3029           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
3030 @*/
3031 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3032 {
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   PetscValidType(mat, 1);
3036   mat->factortype = t;
3037   PetscFunctionReturn(PETSC_SUCCESS);
3038 }
3039 
3040 /*@
3041   MatGetInfo - Returns information about matrix storage (number of
3042   nonzeros, memory, etc.).
3043 
3044   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3045 
3046   Input Parameters:
3047 + mat  - the matrix
3048 - 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)
3049 
3050   Output Parameter:
3051 . info - matrix information context
3052 
3053   Options Database Key:
3054 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3055 
3056   Level: intermediate
3057 
3058   Notes:
3059   The `MatInfo` context contains a variety of matrix data, including
3060   number of nonzeros allocated and used, number of mallocs during
3061   matrix assembly, etc.  Additional information for factored matrices
3062   is provided (such as the fill ratio, number of mallocs during
3063   factorization, etc.).
3064 
3065   Example:
3066   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3067   data within the `MatInfo` context.  For example,
3068 .vb
3069       MatInfo info;
3070       Mat     A;
3071       double  mal, nz_a, nz_u;
3072 
3073       MatGetInfo(A, MAT_LOCAL, &info);
3074       mal  = info.mallocs;
3075       nz_a = info.nz_allocated;
3076 .ve
3077 
3078 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3079 @*/
3080 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3081 {
3082   PetscFunctionBegin;
3083   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3084   PetscValidType(mat, 1);
3085   PetscAssertPointer(info, 3);
3086   MatCheckPreallocated(mat, 1);
3087   PetscUseTypeMethod(mat, getinfo, flag, info);
3088   PetscFunctionReturn(PETSC_SUCCESS);
3089 }
3090 
3091 /*
3092    This is used by external packages where it is not easy to get the info from the actual
3093    matrix factorization.
3094 */
3095 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3096 {
3097   PetscFunctionBegin;
3098   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3099   PetscFunctionReturn(PETSC_SUCCESS);
3100 }
3101 
3102 /*@
3103   MatLUFactor - Performs in-place LU factorization of matrix.
3104 
3105   Collective
3106 
3107   Input Parameters:
3108 + mat  - the matrix
3109 . row  - row permutation
3110 . col  - column permutation
3111 - info - options for factorization, includes
3112 .vb
3113           fill - expected fill as ratio of original fill.
3114           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3115                    Run with the option -info to determine an optimal value to use
3116 .ve
3117 
3118   Level: developer
3119 
3120   Notes:
3121   Most users should employ the `KSP` interface for linear solvers
3122   instead of working directly with matrix algebra routines such as this.
3123   See, e.g., `KSPCreate()`.
3124 
3125   This changes the state of the matrix to a factored matrix; it cannot be used
3126   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3127 
3128   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3129   when not using `KSP`.
3130 
3131   Developer Note:
3132   The Fortran interface is not autogenerated as the
3133   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3134 
3135 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3136           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3137 @*/
3138 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3139 {
3140   MatFactorInfo tinfo;
3141 
3142   PetscFunctionBegin;
3143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3144   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3145   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3146   if (info) PetscAssertPointer(info, 4);
3147   PetscValidType(mat, 1);
3148   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3149   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3150   MatCheckPreallocated(mat, 1);
3151   if (!info) {
3152     PetscCall(MatFactorInfoInitialize(&tinfo));
3153     info = &tinfo;
3154   }
3155 
3156   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3157   PetscUseTypeMethod(mat, lufactor, row, col, info);
3158   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3159   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3160   PetscFunctionReturn(PETSC_SUCCESS);
3161 }
3162 
3163 /*@
3164   MatILUFactor - Performs in-place ILU factorization of matrix.
3165 
3166   Collective
3167 
3168   Input Parameters:
3169 + mat  - the matrix
3170 . row  - row permutation
3171 . col  - column permutation
3172 - info - structure containing
3173 .vb
3174       levels - number of levels of fill.
3175       expected fill - as ratio of original fill.
3176       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3177                 missing diagonal entries)
3178 .ve
3179 
3180   Level: developer
3181 
3182   Notes:
3183   Most users should employ the `KSP` interface for linear solvers
3184   instead of working directly with matrix algebra routines such as this.
3185   See, e.g., `KSPCreate()`.
3186 
3187   Probably really in-place only when level of fill is zero, otherwise allocates
3188   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3189   when not using `KSP`.
3190 
3191   Developer Note:
3192   The Fortran interface is not autogenerated as the
3193   interface definition cannot be generated correctly [due to MatFactorInfo]
3194 
3195 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3196 @*/
3197 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3198 {
3199   PetscFunctionBegin;
3200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3201   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3202   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3203   PetscAssertPointer(info, 4);
3204   PetscValidType(mat, 1);
3205   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3206   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3207   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3208   MatCheckPreallocated(mat, 1);
3209 
3210   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3211   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3212   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3213   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3214   PetscFunctionReturn(PETSC_SUCCESS);
3215 }
3216 
3217 /*@
3218   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3219   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3220 
3221   Collective
3222 
3223   Input Parameters:
3224 + fact - the factor matrix obtained with `MatGetFactor()`
3225 . mat  - the matrix
3226 . row  - the row permutation
3227 . col  - the column permutation
3228 - info - options for factorization, includes
3229 .vb
3230           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3231           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3232 .ve
3233 
3234   Level: developer
3235 
3236   Notes:
3237   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3238 
3239   Most users should employ the simplified `KSP` interface for linear solvers
3240   instead of working directly with matrix algebra routines such as this.
3241   See, e.g., `KSPCreate()`.
3242 
3243   Developer Note:
3244   The Fortran interface is not autogenerated as the
3245   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3246 
3247 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3248 @*/
3249 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3250 {
3251   MatFactorInfo tinfo;
3252 
3253   PetscFunctionBegin;
3254   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3255   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3256   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3257   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3258   if (info) PetscAssertPointer(info, 5);
3259   PetscValidType(fact, 1);
3260   PetscValidType(mat, 2);
3261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3263   MatCheckPreallocated(mat, 2);
3264   if (!info) {
3265     PetscCall(MatFactorInfoInitialize(&tinfo));
3266     info = &tinfo;
3267   }
3268 
3269   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3270   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3271   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3272   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3273   PetscFunctionReturn(PETSC_SUCCESS);
3274 }
3275 
3276 /*@
3277   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3278   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3279 
3280   Collective
3281 
3282   Input Parameters:
3283 + fact - the factor matrix obtained with `MatGetFactor()`
3284 . mat  - the matrix
3285 - info - options for factorization
3286 
3287   Level: developer
3288 
3289   Notes:
3290   See `MatLUFactor()` for in-place factorization.  See
3291   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3292 
3293   Most users should employ the `KSP` interface for linear solvers
3294   instead of working directly with matrix algebra routines such as this.
3295   See, e.g., `KSPCreate()`.
3296 
3297   Developer Note:
3298   The Fortran interface is not autogenerated as the
3299   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3300 
3301 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3302 @*/
3303 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3304 {
3305   MatFactorInfo tinfo;
3306 
3307   PetscFunctionBegin;
3308   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3310   PetscValidType(fact, 1);
3311   PetscValidType(mat, 2);
3312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3313   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,
3314              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3315 
3316   MatCheckPreallocated(mat, 2);
3317   if (!info) {
3318     PetscCall(MatFactorInfoInitialize(&tinfo));
3319     info = &tinfo;
3320   }
3321 
3322   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3323   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3324   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3325   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3326   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3327   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3328   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3329   PetscFunctionReturn(PETSC_SUCCESS);
3330 }
3331 
3332 /*@
3333   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3334   symmetric matrix.
3335 
3336   Collective
3337 
3338   Input Parameters:
3339 + mat  - the matrix
3340 . perm - row and column permutations
3341 - info - expected fill as ratio of original fill
3342 
3343   Level: developer
3344 
3345   Notes:
3346   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3347   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3348 
3349   Most users should employ the `KSP` interface for linear solvers
3350   instead of working directly with matrix algebra routines such as this.
3351   See, e.g., `KSPCreate()`.
3352 
3353   Developer Note:
3354   The Fortran interface is not autogenerated as the
3355   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3356 
3357 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3358           `MatGetOrdering()`
3359 @*/
3360 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3361 {
3362   MatFactorInfo tinfo;
3363 
3364   PetscFunctionBegin;
3365   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3366   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3367   if (info) PetscAssertPointer(info, 3);
3368   PetscValidType(mat, 1);
3369   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3370   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3371   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3372   MatCheckPreallocated(mat, 1);
3373   if (!info) {
3374     PetscCall(MatFactorInfoInitialize(&tinfo));
3375     info = &tinfo;
3376   }
3377 
3378   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3379   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3380   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3381   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3382   PetscFunctionReturn(PETSC_SUCCESS);
3383 }
3384 
3385 /*@
3386   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3387   of a symmetric matrix.
3388 
3389   Collective
3390 
3391   Input Parameters:
3392 + fact - the factor matrix obtained with `MatGetFactor()`
3393 . mat  - the matrix
3394 . perm - row and column permutations
3395 - info - options for factorization, includes
3396 .vb
3397           fill - expected fill as ratio of original fill.
3398           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3399                    Run with the option -info to determine an optimal value to use
3400 .ve
3401 
3402   Level: developer
3403 
3404   Notes:
3405   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3406   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3407 
3408   Most users should employ the `KSP` interface for linear solvers
3409   instead of working directly with matrix algebra routines such as this.
3410   See, e.g., `KSPCreate()`.
3411 
3412   Developer Note:
3413   The Fortran interface is not autogenerated as the
3414   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3415 
3416 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3417           `MatGetOrdering()`
3418 @*/
3419 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3420 {
3421   MatFactorInfo tinfo;
3422 
3423   PetscFunctionBegin;
3424   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3425   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3426   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3427   if (info) PetscAssertPointer(info, 4);
3428   PetscValidType(fact, 1);
3429   PetscValidType(mat, 2);
3430   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3433   MatCheckPreallocated(mat, 2);
3434   if (!info) {
3435     PetscCall(MatFactorInfoInitialize(&tinfo));
3436     info = &tinfo;
3437   }
3438 
3439   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3440   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3441   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3442   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3443   PetscFunctionReturn(PETSC_SUCCESS);
3444 }
3445 
3446 /*@
3447   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3448   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3449   `MatCholeskyFactorSymbolic()`.
3450 
3451   Collective
3452 
3453   Input Parameters:
3454 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3455 . mat  - the initial matrix that is to be factored
3456 - info - options for factorization
3457 
3458   Level: developer
3459 
3460   Note:
3461   Most users should employ the `KSP` interface for linear solvers
3462   instead of working directly with matrix algebra routines such as this.
3463   See, e.g., `KSPCreate()`.
3464 
3465   Developer Note:
3466   The Fortran interface is not autogenerated as the
3467   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3468 
3469 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3470 @*/
3471 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3472 {
3473   MatFactorInfo tinfo;
3474 
3475   PetscFunctionBegin;
3476   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3478   PetscValidType(fact, 1);
3479   PetscValidType(mat, 2);
3480   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3481   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,
3482              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3483   MatCheckPreallocated(mat, 2);
3484   if (!info) {
3485     PetscCall(MatFactorInfoInitialize(&tinfo));
3486     info = &tinfo;
3487   }
3488 
3489   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3490   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3491   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3492   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3493   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3494   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3495   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3496   PetscFunctionReturn(PETSC_SUCCESS);
3497 }
3498 
3499 /*@
3500   MatQRFactor - Performs in-place QR factorization of matrix.
3501 
3502   Collective
3503 
3504   Input Parameters:
3505 + mat  - the matrix
3506 . col  - column permutation
3507 - info - options for factorization, includes
3508 .vb
3509           fill - expected fill as ratio of original fill.
3510           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3511                    Run with the option -info to determine an optimal value to use
3512 .ve
3513 
3514   Level: developer
3515 
3516   Notes:
3517   Most users should employ the `KSP` interface for linear solvers
3518   instead of working directly with matrix algebra routines such as this.
3519   See, e.g., `KSPCreate()`.
3520 
3521   This changes the state of the matrix to a factored matrix; it cannot be used
3522   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3523 
3524   Developer Note:
3525   The Fortran interface is not autogenerated as the
3526   interface definition cannot be generated correctly [due to MatFactorInfo]
3527 
3528 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3529           `MatSetUnfactored()`
3530 @*/
3531 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3532 {
3533   PetscFunctionBegin;
3534   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3535   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3536   if (info) PetscAssertPointer(info, 3);
3537   PetscValidType(mat, 1);
3538   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3539   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3540   MatCheckPreallocated(mat, 1);
3541   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3542   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3543   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3544   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3545   PetscFunctionReturn(PETSC_SUCCESS);
3546 }
3547 
3548 /*@
3549   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3550   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3551 
3552   Collective
3553 
3554   Input Parameters:
3555 + fact - the factor matrix obtained with `MatGetFactor()`
3556 . mat  - the matrix
3557 . col  - column permutation
3558 - info - options for factorization, includes
3559 .vb
3560           fill - expected fill as ratio of original fill.
3561           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3562                    Run with the option -info to determine an optimal value to use
3563 .ve
3564 
3565   Level: developer
3566 
3567   Note:
3568   Most users should employ the `KSP` interface for linear solvers
3569   instead of working directly with matrix algebra routines such as this.
3570   See, e.g., `KSPCreate()`.
3571 
3572   Developer Note:
3573   The Fortran interface is not autogenerated as the
3574   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3575 
3576 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3577 @*/
3578 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3579 {
3580   MatFactorInfo tinfo;
3581 
3582   PetscFunctionBegin;
3583   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3585   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3586   if (info) PetscAssertPointer(info, 4);
3587   PetscValidType(fact, 1);
3588   PetscValidType(mat, 2);
3589   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3590   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3591   MatCheckPreallocated(mat, 2);
3592   if (!info) {
3593     PetscCall(MatFactorInfoInitialize(&tinfo));
3594     info = &tinfo;
3595   }
3596 
3597   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3598   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3599   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3600   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3601   PetscFunctionReturn(PETSC_SUCCESS);
3602 }
3603 
3604 /*@
3605   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3606   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3607 
3608   Collective
3609 
3610   Input Parameters:
3611 + fact - the factor matrix obtained with `MatGetFactor()`
3612 . mat  - the matrix
3613 - info - options for factorization
3614 
3615   Level: developer
3616 
3617   Notes:
3618   See `MatQRFactor()` for in-place factorization.
3619 
3620   Most users should employ the `KSP` interface for linear solvers
3621   instead of working directly with matrix algebra routines such as this.
3622   See, e.g., `KSPCreate()`.
3623 
3624   Developer Note:
3625   The Fortran interface is not autogenerated as the
3626   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3627 
3628 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3629 @*/
3630 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3631 {
3632   MatFactorInfo tinfo;
3633 
3634   PetscFunctionBegin;
3635   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3637   PetscValidType(fact, 1);
3638   PetscValidType(mat, 2);
3639   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3640   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,
3641              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3642 
3643   MatCheckPreallocated(mat, 2);
3644   if (!info) {
3645     PetscCall(MatFactorInfoInitialize(&tinfo));
3646     info = &tinfo;
3647   }
3648 
3649   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3650   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3651   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3652   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3653   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3654   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3655   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3656   PetscFunctionReturn(PETSC_SUCCESS);
3657 }
3658 
3659 /*@
3660   MatSolve - Solves $A x = b$, given a factored matrix.
3661 
3662   Neighbor-wise Collective
3663 
3664   Input Parameters:
3665 + mat - the factored matrix
3666 - b   - the right-hand-side vector
3667 
3668   Output Parameter:
3669 . x - the result vector
3670 
3671   Level: developer
3672 
3673   Notes:
3674   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3675   call `MatSolve`(A,x,x).
3676 
3677   Most users should employ the `KSP` interface for linear solvers
3678   instead of working directly with matrix algebra routines such as this.
3679   See, e.g., `KSPCreate()`.
3680 
3681 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3682 @*/
3683 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3684 {
3685   PetscFunctionBegin;
3686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3687   PetscValidType(mat, 1);
3688   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3689   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3690   PetscCheckSameComm(mat, 1, b, 2);
3691   PetscCheckSameComm(mat, 1, x, 3);
3692   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3693   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);
3694   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);
3695   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);
3696   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3697   MatCheckPreallocated(mat, 1);
3698 
3699   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3700   PetscCall(VecFlag(x, mat->factorerrortype));
3701   if (mat->factorerrortype) {
3702     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3703   } else PetscUseTypeMethod(mat, solve, b, x);
3704   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3705   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3706   PetscFunctionReturn(PETSC_SUCCESS);
3707 }
3708 
3709 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3710 {
3711   Vec      b, x;
3712   PetscInt N, i;
3713   PetscErrorCode (*f)(Mat, Vec, Vec);
3714   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3715 
3716   PetscFunctionBegin;
3717   if (A->factorerrortype) {
3718     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3719     PetscCall(MatSetInf(X));
3720     PetscFunctionReturn(PETSC_SUCCESS);
3721   }
3722   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3723   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3724   PetscCall(MatBoundToCPU(A, &Abound));
3725   if (!Abound) {
3726     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3727     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3728   }
3729 #if PetscDefined(HAVE_CUDA)
3730   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3731   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3732 #elif PetscDefined(HAVE_HIP)
3733   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3734   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3735 #endif
3736   PetscCall(MatGetSize(B, NULL, &N));
3737   for (i = 0; i < N; i++) {
3738     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3739     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3740     PetscCall((*f)(A, b, x));
3741     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3742     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3743   }
3744   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3745   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3746   PetscFunctionReturn(PETSC_SUCCESS);
3747 }
3748 
3749 /*@
3750   MatMatSolve - Solves $A X = B$, given a factored matrix.
3751 
3752   Neighbor-wise Collective
3753 
3754   Input Parameters:
3755 + A - the factored matrix
3756 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3757 
3758   Output Parameter:
3759 . X - the result matrix (dense matrix)
3760 
3761   Level: developer
3762 
3763   Note:
3764   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3765   otherwise, `B` and `X` cannot be the same.
3766 
3767 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3768 @*/
3769 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3770 {
3771   PetscFunctionBegin;
3772   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3773   PetscValidType(A, 1);
3774   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3775   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3776   PetscCheckSameComm(A, 1, B, 2);
3777   PetscCheckSameComm(A, 1, X, 3);
3778   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);
3779   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);
3780   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");
3781   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3782   MatCheckPreallocated(A, 1);
3783 
3784   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3785   if (!A->ops->matsolve) {
3786     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3787     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3788   } else PetscUseTypeMethod(A, matsolve, B, X);
3789   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3790   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3791   PetscFunctionReturn(PETSC_SUCCESS);
3792 }
3793 
3794 /*@
3795   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3796 
3797   Neighbor-wise Collective
3798 
3799   Input Parameters:
3800 + A - the factored matrix
3801 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3802 
3803   Output Parameter:
3804 . X - the result matrix (dense matrix)
3805 
3806   Level: developer
3807 
3808   Note:
3809   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3810   call `MatMatSolveTranspose`(A,X,X).
3811 
3812 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3813 @*/
3814 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3815 {
3816   PetscFunctionBegin;
3817   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3818   PetscValidType(A, 1);
3819   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3820   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3821   PetscCheckSameComm(A, 1, B, 2);
3822   PetscCheckSameComm(A, 1, X, 3);
3823   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3824   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);
3825   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);
3826   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);
3827   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");
3828   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3829   MatCheckPreallocated(A, 1);
3830 
3831   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3832   if (!A->ops->matsolvetranspose) {
3833     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3834     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3835   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3836   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3837   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3838   PetscFunctionReturn(PETSC_SUCCESS);
3839 }
3840 
3841 /*@
3842   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3843 
3844   Neighbor-wise Collective
3845 
3846   Input Parameters:
3847 + A  - the factored matrix
3848 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3849 
3850   Output Parameter:
3851 . X - the result matrix (dense matrix)
3852 
3853   Level: developer
3854 
3855   Note:
3856   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
3857   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3858 
3859 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3860 @*/
3861 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3862 {
3863   PetscFunctionBegin;
3864   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3865   PetscValidType(A, 1);
3866   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3867   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3868   PetscCheckSameComm(A, 1, Bt, 2);
3869   PetscCheckSameComm(A, 1, X, 3);
3870 
3871   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3872   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);
3873   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);
3874   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");
3875   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3876   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3877   MatCheckPreallocated(A, 1);
3878 
3879   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3880   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3881   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3882   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3883   PetscFunctionReturn(PETSC_SUCCESS);
3884 }
3885 
3886 /*@
3887   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3888   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3889 
3890   Neighbor-wise Collective
3891 
3892   Input Parameters:
3893 + mat - the factored matrix
3894 - b   - the right-hand-side vector
3895 
3896   Output Parameter:
3897 . x - the result vector
3898 
3899   Level: developer
3900 
3901   Notes:
3902   `MatSolve()` should be used for most applications, as it performs
3903   a forward solve followed by a backward solve.
3904 
3905   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3906   call `MatForwardSolve`(A,x,x).
3907 
3908   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3909   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3910   `MatForwardSolve()` solves $U^T*D y = b$, and
3911   `MatBackwardSolve()` solves $U x = y$.
3912   Thus they do not provide a symmetric preconditioner.
3913 
3914 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3915 @*/
3916 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3917 {
3918   PetscFunctionBegin;
3919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3920   PetscValidType(mat, 1);
3921   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3922   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3923   PetscCheckSameComm(mat, 1, b, 2);
3924   PetscCheckSameComm(mat, 1, x, 3);
3925   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3926   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);
3927   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);
3928   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);
3929   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3930   MatCheckPreallocated(mat, 1);
3931 
3932   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3933   PetscUseTypeMethod(mat, forwardsolve, b, x);
3934   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3935   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3936   PetscFunctionReturn(PETSC_SUCCESS);
3937 }
3938 
3939 /*@
3940   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3941   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3942 
3943   Neighbor-wise Collective
3944 
3945   Input Parameters:
3946 + mat - the factored matrix
3947 - b   - the right-hand-side vector
3948 
3949   Output Parameter:
3950 . x - the result vector
3951 
3952   Level: developer
3953 
3954   Notes:
3955   `MatSolve()` should be used for most applications, as it performs
3956   a forward solve followed by a backward solve.
3957 
3958   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3959   call `MatBackwardSolve`(A,x,x).
3960 
3961   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3962   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3963   `MatForwardSolve()` solves $U^T*D y = b$, and
3964   `MatBackwardSolve()` solves $U x = y$.
3965   Thus they do not provide a symmetric preconditioner.
3966 
3967 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3968 @*/
3969 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3970 {
3971   PetscFunctionBegin;
3972   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3973   PetscValidType(mat, 1);
3974   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3975   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3976   PetscCheckSameComm(mat, 1, b, 2);
3977   PetscCheckSameComm(mat, 1, x, 3);
3978   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3979   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);
3980   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);
3981   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);
3982   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3983   MatCheckPreallocated(mat, 1);
3984 
3985   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3986   PetscUseTypeMethod(mat, backwardsolve, b, x);
3987   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3988   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3989   PetscFunctionReturn(PETSC_SUCCESS);
3990 }
3991 
3992 /*@
3993   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3994 
3995   Neighbor-wise Collective
3996 
3997   Input Parameters:
3998 + mat - the factored matrix
3999 . b   - the right-hand-side vector
4000 - y   - the vector to be added to
4001 
4002   Output Parameter:
4003 . x - the result vector
4004 
4005   Level: developer
4006 
4007   Note:
4008   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4009   call `MatSolveAdd`(A,x,y,x).
4010 
4011 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
4012 @*/
4013 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
4014 {
4015   PetscScalar one = 1.0;
4016   Vec         tmp;
4017 
4018   PetscFunctionBegin;
4019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4020   PetscValidType(mat, 1);
4021   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4022   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4023   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4024   PetscCheckSameComm(mat, 1, b, 2);
4025   PetscCheckSameComm(mat, 1, y, 3);
4026   PetscCheckSameComm(mat, 1, x, 4);
4027   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4028   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);
4029   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);
4030   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);
4031   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);
4032   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);
4033   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4034   MatCheckPreallocated(mat, 1);
4035 
4036   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4037   PetscCall(VecFlag(x, mat->factorerrortype));
4038   if (mat->factorerrortype) {
4039     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4040   } else if (mat->ops->solveadd) {
4041     PetscUseTypeMethod(mat, solveadd, b, y, x);
4042   } else {
4043     /* do the solve then the add manually */
4044     if (x != y) {
4045       PetscCall(MatSolve(mat, b, x));
4046       PetscCall(VecAXPY(x, one, y));
4047     } else {
4048       PetscCall(VecDuplicate(x, &tmp));
4049       PetscCall(VecCopy(x, tmp));
4050       PetscCall(MatSolve(mat, b, x));
4051       PetscCall(VecAXPY(x, one, tmp));
4052       PetscCall(VecDestroy(&tmp));
4053     }
4054   }
4055   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4056   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4057   PetscFunctionReturn(PETSC_SUCCESS);
4058 }
4059 
4060 /*@
4061   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4062 
4063   Neighbor-wise Collective
4064 
4065   Input Parameters:
4066 + mat - the factored matrix
4067 - b   - the right-hand-side vector
4068 
4069   Output Parameter:
4070 . x - the result vector
4071 
4072   Level: developer
4073 
4074   Notes:
4075   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4076   call `MatSolveTranspose`(A,x,x).
4077 
4078   Most users should employ the `KSP` interface for linear solvers
4079   instead of working directly with matrix algebra routines such as this.
4080   See, e.g., `KSPCreate()`.
4081 
4082 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4083 @*/
4084 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4085 {
4086   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4087 
4088   PetscFunctionBegin;
4089   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4090   PetscValidType(mat, 1);
4091   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4092   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4093   PetscCheckSameComm(mat, 1, b, 2);
4094   PetscCheckSameComm(mat, 1, x, 3);
4095   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4096   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);
4097   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);
4098   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4099   MatCheckPreallocated(mat, 1);
4100   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4101   PetscCall(VecFlag(x, mat->factorerrortype));
4102   if (mat->factorerrortype) {
4103     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4104   } else {
4105     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4106     PetscCall((*f)(mat, b, x));
4107   }
4108   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4109   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4110   PetscFunctionReturn(PETSC_SUCCESS);
4111 }
4112 
4113 /*@
4114   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4115   factored matrix.
4116 
4117   Neighbor-wise Collective
4118 
4119   Input Parameters:
4120 + mat - the factored matrix
4121 . b   - the right-hand-side vector
4122 - y   - the vector to be added to
4123 
4124   Output Parameter:
4125 . x - the result vector
4126 
4127   Level: developer
4128 
4129   Note:
4130   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4131   call `MatSolveTransposeAdd`(A,x,y,x).
4132 
4133 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4134 @*/
4135 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4136 {
4137   PetscScalar one = 1.0;
4138   Vec         tmp;
4139   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4140 
4141   PetscFunctionBegin;
4142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4143   PetscValidType(mat, 1);
4144   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4145   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4146   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4147   PetscCheckSameComm(mat, 1, b, 2);
4148   PetscCheckSameComm(mat, 1, y, 3);
4149   PetscCheckSameComm(mat, 1, x, 4);
4150   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4151   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);
4152   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);
4153   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);
4154   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);
4155   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4156   MatCheckPreallocated(mat, 1);
4157 
4158   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4159   PetscCall(VecFlag(x, mat->factorerrortype));
4160   if (mat->factorerrortype) {
4161     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4162   } else if (f) {
4163     PetscCall((*f)(mat, b, y, x));
4164   } else {
4165     /* do the solve then the add manually */
4166     if (x != y) {
4167       PetscCall(MatSolveTranspose(mat, b, x));
4168       PetscCall(VecAXPY(x, one, y));
4169     } else {
4170       PetscCall(VecDuplicate(x, &tmp));
4171       PetscCall(VecCopy(x, tmp));
4172       PetscCall(MatSolveTranspose(mat, b, x));
4173       PetscCall(VecAXPY(x, one, tmp));
4174       PetscCall(VecDestroy(&tmp));
4175     }
4176   }
4177   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4178   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4179   PetscFunctionReturn(PETSC_SUCCESS);
4180 }
4181 
4182 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4183 /*@
4184   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4185 
4186   Neighbor-wise Collective
4187 
4188   Input Parameters:
4189 + mat   - the matrix
4190 . b     - the right-hand side
4191 . omega - the relaxation factor
4192 . flag  - flag indicating the type of SOR (see below)
4193 . shift - diagonal shift
4194 . its   - the number of iterations
4195 - lits  - the number of local iterations
4196 
4197   Output Parameter:
4198 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4199 
4200   SOR Flags:
4201 +     `SOR_FORWARD_SWEEP` - forward SOR
4202 .     `SOR_BACKWARD_SWEEP` - backward SOR
4203 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4204 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4205 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4206 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4207 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4208 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4209   upper/lower triangular part of matrix to
4210   vector (with omega)
4211 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4212 
4213   Level: developer
4214 
4215   Notes:
4216   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4217   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4218   on each processor.
4219 
4220   Application programmers will not generally use `MatSOR()` directly,
4221   but instead will employ the `KSP`/`PC` interface.
4222 
4223   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4224 
4225   Most users should employ the `KSP` interface for linear solvers
4226   instead of working directly with matrix algebra routines such as this.
4227   See, e.g., `KSPCreate()`.
4228 
4229   Vectors `x` and `b` CANNOT be the same
4230 
4231   The flags are implemented as bitwise inclusive or operations.
4232   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4233   to specify a zero initial guess for SSOR.
4234 
4235   Developer Note:
4236   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4237 
4238 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4239 @*/
4240 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4241 {
4242   PetscFunctionBegin;
4243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4244   PetscValidType(mat, 1);
4245   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4246   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4247   PetscCheckSameComm(mat, 1, b, 2);
4248   PetscCheckSameComm(mat, 1, x, 8);
4249   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4250   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4251   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);
4252   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);
4253   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);
4254   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4255   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4256   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4257 
4258   MatCheckPreallocated(mat, 1);
4259   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4260   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4261   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4262   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4263   PetscFunctionReturn(PETSC_SUCCESS);
4264 }
4265 
4266 /*
4267       Default matrix copy routine.
4268 */
4269 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4270 {
4271   PetscInt           i, rstart = 0, rend = 0, nz;
4272   const PetscInt    *cwork;
4273   const PetscScalar *vwork;
4274 
4275   PetscFunctionBegin;
4276   if (B->assembled) PetscCall(MatZeroEntries(B));
4277   if (str == SAME_NONZERO_PATTERN) {
4278     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4279     for (i = rstart; i < rend; i++) {
4280       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4281       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4282       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4283     }
4284   } else {
4285     PetscCall(MatAYPX(B, 0.0, A, str));
4286   }
4287   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4288   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4289   PetscFunctionReturn(PETSC_SUCCESS);
4290 }
4291 
4292 /*@
4293   MatCopy - Copies a matrix to another matrix.
4294 
4295   Collective
4296 
4297   Input Parameters:
4298 + A   - the matrix
4299 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4300 
4301   Output Parameter:
4302 . B - where the copy is put
4303 
4304   Level: intermediate
4305 
4306   Notes:
4307   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4308 
4309   `MatCopy()` copies the matrix entries of a matrix to another existing
4310   matrix (after first zeroing the second matrix).  A related routine is
4311   `MatConvert()`, which first creates a new matrix and then copies the data.
4312 
4313 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4314 @*/
4315 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4316 {
4317   PetscInt i;
4318 
4319   PetscFunctionBegin;
4320   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4321   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4322   PetscValidType(A, 1);
4323   PetscValidType(B, 2);
4324   PetscCheckSameComm(A, 1, B, 2);
4325   MatCheckPreallocated(B, 2);
4326   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4327   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4328   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,
4329              A->cmap->N, B->cmap->N);
4330   MatCheckPreallocated(A, 1);
4331   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4332 
4333   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4334   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4335   else PetscCall(MatCopy_Basic(A, B, str));
4336 
4337   B->stencil.dim = A->stencil.dim;
4338   B->stencil.noc = A->stencil.noc;
4339   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4340     B->stencil.dims[i]   = A->stencil.dims[i];
4341     B->stencil.starts[i] = A->stencil.starts[i];
4342   }
4343 
4344   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4345   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4346   PetscFunctionReturn(PETSC_SUCCESS);
4347 }
4348 
4349 /*@
4350   MatConvert - Converts a matrix to another matrix, either of the same
4351   or different type.
4352 
4353   Collective
4354 
4355   Input Parameters:
4356 + mat     - the matrix
4357 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4358             same type as the original matrix.
4359 - reuse   - denotes if the destination matrix is to be created or reused.
4360             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
4361             `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).
4362 
4363   Output Parameter:
4364 . M - pointer to place new matrix
4365 
4366   Level: intermediate
4367 
4368   Notes:
4369   `MatConvert()` first creates a new matrix and then copies the data from
4370   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4371   entries of one matrix to another already existing matrix context.
4372 
4373   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4374   the MPI communicator of the generated matrix is always the same as the communicator
4375   of the input matrix.
4376 
4377 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4378 @*/
4379 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4380 {
4381   PetscBool  sametype, issame, flg;
4382   PetscBool3 issymmetric, ishermitian;
4383   char       convname[256], mtype[256];
4384   Mat        B;
4385 
4386   PetscFunctionBegin;
4387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4388   PetscValidType(mat, 1);
4389   PetscAssertPointer(M, 4);
4390   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4391   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4392   MatCheckPreallocated(mat, 1);
4393 
4394   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4395   if (flg) newtype = mtype;
4396 
4397   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4398   PetscCall(PetscStrcmp(newtype, "same", &issame));
4399   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4400   if (reuse == MAT_REUSE_MATRIX) {
4401     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4402     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4403   }
4404 
4405   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4406     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4407     PetscFunctionReturn(PETSC_SUCCESS);
4408   }
4409 
4410   /* Cache Mat options because some converters use MatHeaderReplace  */
4411   issymmetric = mat->symmetric;
4412   ishermitian = mat->hermitian;
4413 
4414   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4415     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4416     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4417   } else {
4418     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4419     const char *prefix[3]                                 = {"seq", "mpi", ""};
4420     PetscInt    i;
4421     /*
4422        Order of precedence:
4423        0) See if newtype is a superclass of the current matrix.
4424        1) See if a specialized converter is known to the current matrix.
4425        2) See if a specialized converter is known to the desired matrix class.
4426        3) See if a good general converter is registered for the desired class
4427           (as of 6/27/03 only MATMPIADJ falls into this category).
4428        4) See if a good general converter is known for the current matrix.
4429        5) Use a really basic converter.
4430     */
4431 
4432     /* 0) See if newtype is a superclass of the current matrix.
4433           i.e mat is mpiaij and newtype is aij */
4434     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4435       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4436       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4437       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4438       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4439       if (flg) {
4440         if (reuse == MAT_INPLACE_MATRIX) {
4441           PetscCall(PetscInfo(mat, "Early return\n"));
4442           PetscFunctionReturn(PETSC_SUCCESS);
4443         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4444           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4445           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4446           PetscFunctionReturn(PETSC_SUCCESS);
4447         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4448           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4449           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4450           PetscFunctionReturn(PETSC_SUCCESS);
4451         }
4452       }
4453     }
4454     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4455     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4456       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4457       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4458       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4459       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4460       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4461       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4462       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4463       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4464       if (conv) goto foundconv;
4465     }
4466 
4467     /* 2)  See if a specialized converter is known to the desired matrix class. */
4468     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4469     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4470     PetscCall(MatSetType(B, newtype));
4471     for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) {
4472       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4473       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4474       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4475       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4476       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4477       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4478       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4479       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4480       if (conv) {
4481         PetscCall(MatDestroy(&B));
4482         goto foundconv;
4483       }
4484     }
4485 
4486     /* 3) See if a good general converter is registered for the desired class */
4487     conv = B->ops->convertfrom;
4488     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4489     PetscCall(MatDestroy(&B));
4490     if (conv) goto foundconv;
4491 
4492     /* 4) See if a good general converter is known for the current matrix */
4493     if (mat->ops->convert) conv = mat->ops->convert;
4494     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4495     if (conv) goto foundconv;
4496 
4497     /* 5) Use a really basic converter. */
4498     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4499     conv = MatConvert_Basic;
4500 
4501   foundconv:
4502     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4503     PetscCall((*conv)(mat, newtype, reuse, M));
4504     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4505       /* the block sizes must be same if the mappings are copied over */
4506       (*M)->rmap->bs = mat->rmap->bs;
4507       (*M)->cmap->bs = mat->cmap->bs;
4508       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4509       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4510       (*M)->rmap->mapping = mat->rmap->mapping;
4511       (*M)->cmap->mapping = mat->cmap->mapping;
4512     }
4513     (*M)->stencil.dim = mat->stencil.dim;
4514     (*M)->stencil.noc = mat->stencil.noc;
4515     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4516       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4517       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4518     }
4519     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4520   }
4521   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4522 
4523   /* Copy Mat options */
4524   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4525   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4526   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4527   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4528   PetscFunctionReturn(PETSC_SUCCESS);
4529 }
4530 
4531 /*@
4532   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4533 
4534   Not Collective
4535 
4536   Input Parameter:
4537 . mat - the matrix, must be a factored matrix
4538 
4539   Output Parameter:
4540 . type - the string name of the package (do not free this string)
4541 
4542   Level: intermediate
4543 
4544 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4545 @*/
4546 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4547 {
4548   PetscErrorCode (*conv)(Mat, MatSolverType *);
4549 
4550   PetscFunctionBegin;
4551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4552   PetscValidType(mat, 1);
4553   PetscAssertPointer(type, 2);
4554   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4555   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4556   if (conv) PetscCall((*conv)(mat, type));
4557   else *type = MATSOLVERPETSC;
4558   PetscFunctionReturn(PETSC_SUCCESS);
4559 }
4560 
4561 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4562 struct _MatSolverTypeForSpecifcType {
4563   MatType mtype;
4564   /* no entry for MAT_FACTOR_NONE */
4565   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4566   MatSolverTypeForSpecifcType next;
4567 };
4568 
4569 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4570 struct _MatSolverTypeHolder {
4571   char                       *name;
4572   MatSolverTypeForSpecifcType handlers;
4573   MatSolverTypeHolder         next;
4574 };
4575 
4576 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4577 
4578 /*@C
4579   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4580 
4581   Logically Collective, No Fortran Support
4582 
4583   Input Parameters:
4584 + package      - name of the package, for example `petsc` or `superlu`
4585 . mtype        - the matrix type that works with this package
4586 . ftype        - the type of factorization supported by the package
4587 - createfactor - routine that will create the factored matrix ready to be used
4588 
4589   Level: developer
4590 
4591 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4592   `MatGetFactor()`
4593 @*/
4594 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4595 {
4596   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4597   PetscBool                   flg;
4598   MatSolverTypeForSpecifcType inext, iprev = NULL;
4599 
4600   PetscFunctionBegin;
4601   PetscCall(MatInitializePackage());
4602   if (!next) {
4603     PetscCall(PetscNew(&MatSolverTypeHolders));
4604     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4605     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4606     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4607     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4608     PetscFunctionReturn(PETSC_SUCCESS);
4609   }
4610   while (next) {
4611     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4612     if (flg) {
4613       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4614       inext = next->handlers;
4615       while (inext) {
4616         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4617         if (flg) {
4618           inext->createfactor[(int)ftype - 1] = createfactor;
4619           PetscFunctionReturn(PETSC_SUCCESS);
4620         }
4621         iprev = inext;
4622         inext = inext->next;
4623       }
4624       PetscCall(PetscNew(&iprev->next));
4625       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4626       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4627       PetscFunctionReturn(PETSC_SUCCESS);
4628     }
4629     prev = next;
4630     next = next->next;
4631   }
4632   PetscCall(PetscNew(&prev->next));
4633   PetscCall(PetscStrallocpy(package, &prev->next->name));
4634   PetscCall(PetscNew(&prev->next->handlers));
4635   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4636   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4637   PetscFunctionReturn(PETSC_SUCCESS);
4638 }
4639 
4640 /*@C
4641   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4642 
4643   Input Parameters:
4644 + 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
4645 . ftype - the type of factorization supported by the type
4646 - mtype - the matrix type that works with this type
4647 
4648   Output Parameters:
4649 + foundtype    - `PETSC_TRUE` if the type was registered
4650 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4651 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4652 
4653   Calling sequence of `createfactor`:
4654 + A     - the matrix providing the factor matrix
4655 . ftype - the `MatFactorType` of the factor requested
4656 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4657 
4658   Level: developer
4659 
4660   Note:
4661   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4662   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4663   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4664 
4665 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4666           `MatInitializePackage()`
4667 @*/
4668 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4669 {
4670   MatSolverTypeHolder         next = MatSolverTypeHolders;
4671   PetscBool                   flg;
4672   MatSolverTypeForSpecifcType inext;
4673 
4674   PetscFunctionBegin;
4675   if (foundtype) *foundtype = PETSC_FALSE;
4676   if (foundmtype) *foundmtype = PETSC_FALSE;
4677   if (createfactor) *createfactor = NULL;
4678 
4679   if (type) {
4680     while (next) {
4681       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4682       if (flg) {
4683         if (foundtype) *foundtype = PETSC_TRUE;
4684         inext = next->handlers;
4685         while (inext) {
4686           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4687           if (flg) {
4688             if (foundmtype) *foundmtype = PETSC_TRUE;
4689             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4690             PetscFunctionReturn(PETSC_SUCCESS);
4691           }
4692           inext = inext->next;
4693         }
4694       }
4695       next = next->next;
4696     }
4697   } else {
4698     while (next) {
4699       inext = next->handlers;
4700       while (inext) {
4701         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4702         if (flg && inext->createfactor[(int)ftype - 1]) {
4703           if (foundtype) *foundtype = PETSC_TRUE;
4704           if (foundmtype) *foundmtype = PETSC_TRUE;
4705           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4706           PetscFunctionReturn(PETSC_SUCCESS);
4707         }
4708         inext = inext->next;
4709       }
4710       next = next->next;
4711     }
4712     /* try with base classes inext->mtype */
4713     next = MatSolverTypeHolders;
4714     while (next) {
4715       inext = next->handlers;
4716       while (inext) {
4717         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4718         if (flg && inext->createfactor[(int)ftype - 1]) {
4719           if (foundtype) *foundtype = PETSC_TRUE;
4720           if (foundmtype) *foundmtype = PETSC_TRUE;
4721           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4722           PetscFunctionReturn(PETSC_SUCCESS);
4723         }
4724         inext = inext->next;
4725       }
4726       next = next->next;
4727     }
4728   }
4729   PetscFunctionReturn(PETSC_SUCCESS);
4730 }
4731 
4732 PetscErrorCode MatSolverTypeDestroy(void)
4733 {
4734   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4735   MatSolverTypeForSpecifcType inext, iprev;
4736 
4737   PetscFunctionBegin;
4738   while (next) {
4739     PetscCall(PetscFree(next->name));
4740     inext = next->handlers;
4741     while (inext) {
4742       PetscCall(PetscFree(inext->mtype));
4743       iprev = inext;
4744       inext = inext->next;
4745       PetscCall(PetscFree(iprev));
4746     }
4747     prev = next;
4748     next = next->next;
4749     PetscCall(PetscFree(prev));
4750   }
4751   MatSolverTypeHolders = NULL;
4752   PetscFunctionReturn(PETSC_SUCCESS);
4753 }
4754 
4755 /*@
4756   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4757 
4758   Logically Collective
4759 
4760   Input Parameter:
4761 . mat - the matrix
4762 
4763   Output Parameter:
4764 . flg - `PETSC_TRUE` if uses the ordering
4765 
4766   Level: developer
4767 
4768   Note:
4769   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4770   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4771 
4772 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4773 @*/
4774 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4775 {
4776   PetscFunctionBegin;
4777   *flg = mat->canuseordering;
4778   PetscFunctionReturn(PETSC_SUCCESS);
4779 }
4780 
4781 /*@
4782   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4783 
4784   Logically Collective
4785 
4786   Input Parameters:
4787 + mat   - the matrix obtained with `MatGetFactor()`
4788 - ftype - the factorization type to be used
4789 
4790   Output Parameter:
4791 . otype - the preferred ordering type
4792 
4793   Level: developer
4794 
4795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4796 @*/
4797 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4798 {
4799   PetscFunctionBegin;
4800   *otype = mat->preferredordering[ftype];
4801   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4802   PetscFunctionReturn(PETSC_SUCCESS);
4803 }
4804 
4805 /*@
4806   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4807 
4808   Collective
4809 
4810   Input Parameters:
4811 + mat   - the matrix
4812 . 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
4813           the other criteria is returned
4814 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4815 
4816   Output Parameter:
4817 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4818 
4819   Options Database Keys:
4820 + -pc_factor_mat_solver_type <type>    - choose the type at run time. When using `KSP` solvers
4821 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device
4822 - -pc_factor_mat_solve_on_host <bool>  - do mat solve on host (with device matrices). Default is doing it on device
4823 
4824   Level: intermediate
4825 
4826   Notes:
4827   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4828   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4829 
4830   Users usually access the factorization solvers via `KSP`
4831 
4832   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4833   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
4834 
4835   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4836   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4837   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4838 
4839   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4840   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4841   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4842 
4843   Developer Note:
4844   This should actually be called `MatCreateFactor()` since it creates a new factor object
4845 
4846 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4847           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4848           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4849 @*/
4850 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4851 {
4852   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4853   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4854 
4855   PetscFunctionBegin;
4856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4857   PetscValidType(mat, 1);
4858 
4859   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4860   MatCheckPreallocated(mat, 1);
4861 
4862   PetscCall(MatIsShell(mat, &shell));
4863   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4864   if (hasop) {
4865     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4866     PetscFunctionReturn(PETSC_SUCCESS);
4867   }
4868 
4869   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4870   if (!foundtype) {
4871     if (type) {
4872       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],
4873               ((PetscObject)mat)->type_name, type);
4874     } else {
4875       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);
4876     }
4877   }
4878   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4879   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);
4880 
4881   PetscCall((*conv)(mat, ftype, f));
4882   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4883   PetscFunctionReturn(PETSC_SUCCESS);
4884 }
4885 
4886 /*@
4887   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4888 
4889   Not Collective
4890 
4891   Input Parameters:
4892 + mat   - the matrix
4893 . type  - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default)
4894 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4895 
4896   Output Parameter:
4897 . flg - PETSC_TRUE if the factorization is available
4898 
4899   Level: intermediate
4900 
4901   Notes:
4902   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4903   such as pastix, superlu, mumps etc.
4904 
4905   PETSc must have been ./configure to use the external solver, using the option --download-package
4906 
4907   Developer Note:
4908   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4909 
4910 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4911           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4912 @*/
4913 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4914 {
4915   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4916 
4917   PetscFunctionBegin;
4918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4919   PetscAssertPointer(flg, 4);
4920 
4921   *flg = PETSC_FALSE;
4922   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4923 
4924   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4925   MatCheckPreallocated(mat, 1);
4926 
4927   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4928   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4929   PetscFunctionReturn(PETSC_SUCCESS);
4930 }
4931 
4932 /*@
4933   MatDuplicate - Duplicates a matrix including the non-zero structure.
4934 
4935   Collective
4936 
4937   Input Parameters:
4938 + mat - the matrix
4939 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4940         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4941 
4942   Output Parameter:
4943 . M - pointer to place new matrix
4944 
4945   Level: intermediate
4946 
4947   Notes:
4948   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4949 
4950   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4951 
4952   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.
4953 
4954   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4955   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4956   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4957 
4958 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4959 @*/
4960 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4961 {
4962   Mat         B;
4963   VecType     vtype;
4964   PetscInt    i;
4965   PetscObject dm, container_h, container_d;
4966   void (*viewf)(void);
4967 
4968   PetscFunctionBegin;
4969   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4970   PetscValidType(mat, 1);
4971   PetscAssertPointer(M, 3);
4972   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4973   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4974   MatCheckPreallocated(mat, 1);
4975 
4976   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4977   PetscUseTypeMethod(mat, duplicate, op, M);
4978   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4979   B = *M;
4980 
4981   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4982   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4983   PetscCall(MatGetVecType(mat, &vtype));
4984   PetscCall(MatSetVecType(B, vtype));
4985 
4986   B->stencil.dim = mat->stencil.dim;
4987   B->stencil.noc = mat->stencil.noc;
4988   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4989     B->stencil.dims[i]   = mat->stencil.dims[i];
4990     B->stencil.starts[i] = mat->stencil.starts[i];
4991   }
4992 
4993   B->nooffproczerorows = mat->nooffproczerorows;
4994   B->nooffprocentries  = mat->nooffprocentries;
4995 
4996   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4997   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4998   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4999   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
5000   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
5001   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
5002   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
5003   PetscCall(PetscObjectStateIncrease((PetscObject)B));
5004   PetscFunctionReturn(PETSC_SUCCESS);
5005 }
5006 
5007 /*@
5008   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
5009 
5010   Logically Collective
5011 
5012   Input Parameter:
5013 . mat - the matrix
5014 
5015   Output Parameter:
5016 . v - the diagonal of the matrix
5017 
5018   Level: intermediate
5019 
5020   Note:
5021   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5022   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5023   is larger than `ndiag`, the values of the remaining entries are unspecified.
5024 
5025   Currently only correct in parallel for square matrices.
5026 
5027 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5028 @*/
5029 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5030 {
5031   PetscFunctionBegin;
5032   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5033   PetscValidType(mat, 1);
5034   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5035   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5036   MatCheckPreallocated(mat, 1);
5037   if (PetscDefined(USE_DEBUG)) {
5038     PetscInt nv, row, col, ndiag;
5039 
5040     PetscCall(VecGetLocalSize(v, &nv));
5041     PetscCall(MatGetLocalSize(mat, &row, &col));
5042     ndiag = PetscMin(row, col);
5043     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);
5044   }
5045 
5046   PetscUseTypeMethod(mat, getdiagonal, v);
5047   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5048   PetscFunctionReturn(PETSC_SUCCESS);
5049 }
5050 
5051 /*@
5052   MatGetRowMin - Gets the minimum value (of the real part) of each
5053   row of the matrix
5054 
5055   Logically Collective
5056 
5057   Input Parameter:
5058 . mat - the matrix
5059 
5060   Output Parameters:
5061 + v   - the vector for storing the maximums
5062 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5063 
5064   Level: intermediate
5065 
5066   Note:
5067   The result of this call are the same as if one converted the matrix to dense format
5068   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5069 
5070   This code is only implemented for a couple of matrix formats.
5071 
5072 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5073           `MatGetRowMax()`
5074 @*/
5075 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5076 {
5077   PetscFunctionBegin;
5078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5079   PetscValidType(mat, 1);
5080   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5081   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5082 
5083   if (!mat->cmap->N) {
5084     PetscCall(VecSet(v, PETSC_MAX_REAL));
5085     if (idx) {
5086       PetscInt i, m = mat->rmap->n;
5087       for (i = 0; i < m; i++) idx[i] = -1;
5088     }
5089   } else {
5090     MatCheckPreallocated(mat, 1);
5091   }
5092   PetscUseTypeMethod(mat, getrowmin, v, idx);
5093   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5094   PetscFunctionReturn(PETSC_SUCCESS);
5095 }
5096 
5097 /*@
5098   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5099   row of the matrix
5100 
5101   Logically Collective
5102 
5103   Input Parameter:
5104 . mat - the matrix
5105 
5106   Output Parameters:
5107 + v   - the vector for storing the minimums
5108 - idx - the indices of the column found for each row (or `NULL` if not needed)
5109 
5110   Level: intermediate
5111 
5112   Notes:
5113   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5114   row is 0 (the first column).
5115 
5116   This code is only implemented for a couple of matrix formats.
5117 
5118 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5119 @*/
5120 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5121 {
5122   PetscFunctionBegin;
5123   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5124   PetscValidType(mat, 1);
5125   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5126   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5127   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5128 
5129   if (!mat->cmap->N) {
5130     PetscCall(VecSet(v, 0.0));
5131     if (idx) {
5132       PetscInt i, m = mat->rmap->n;
5133       for (i = 0; i < m; i++) idx[i] = -1;
5134     }
5135   } else {
5136     MatCheckPreallocated(mat, 1);
5137     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5138     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5139   }
5140   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5141   PetscFunctionReturn(PETSC_SUCCESS);
5142 }
5143 
5144 /*@
5145   MatGetRowMax - Gets the maximum value (of the real part) of each
5146   row of the matrix
5147 
5148   Logically Collective
5149 
5150   Input Parameter:
5151 . mat - the matrix
5152 
5153   Output Parameters:
5154 + v   - the vector for storing the maximums
5155 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5156 
5157   Level: intermediate
5158 
5159   Notes:
5160   The result of this call are the same as if one converted the matrix to dense format
5161   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5162 
5163   This code is only implemented for a couple of matrix formats.
5164 
5165 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5166 @*/
5167 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5168 {
5169   PetscFunctionBegin;
5170   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5171   PetscValidType(mat, 1);
5172   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5173   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5174 
5175   if (!mat->cmap->N) {
5176     PetscCall(VecSet(v, PETSC_MIN_REAL));
5177     if (idx) {
5178       PetscInt i, m = mat->rmap->n;
5179       for (i = 0; i < m; i++) idx[i] = -1;
5180     }
5181   } else {
5182     MatCheckPreallocated(mat, 1);
5183     PetscUseTypeMethod(mat, getrowmax, v, idx);
5184   }
5185   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5186   PetscFunctionReturn(PETSC_SUCCESS);
5187 }
5188 
5189 /*@
5190   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5191   row of the matrix
5192 
5193   Logically Collective
5194 
5195   Input Parameter:
5196 . mat - the matrix
5197 
5198   Output Parameters:
5199 + v   - the vector for storing the maximums
5200 - idx - the indices of the column found for each row (or `NULL` if not needed)
5201 
5202   Level: intermediate
5203 
5204   Notes:
5205   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5206   row is 0 (the first column).
5207 
5208   This code is only implemented for a couple of matrix formats.
5209 
5210 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5211 @*/
5212 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5213 {
5214   PetscFunctionBegin;
5215   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5216   PetscValidType(mat, 1);
5217   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5218   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5219 
5220   if (!mat->cmap->N) {
5221     PetscCall(VecSet(v, 0.0));
5222     if (idx) {
5223       PetscInt i, m = mat->rmap->n;
5224       for (i = 0; i < m; i++) idx[i] = -1;
5225     }
5226   } else {
5227     MatCheckPreallocated(mat, 1);
5228     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5229     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5230   }
5231   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5232   PetscFunctionReturn(PETSC_SUCCESS);
5233 }
5234 
5235 /*@
5236   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5237 
5238   Logically Collective
5239 
5240   Input Parameter:
5241 . mat - the matrix
5242 
5243   Output Parameter:
5244 . v - the vector for storing the sum
5245 
5246   Level: intermediate
5247 
5248   This code is only implemented for a couple of matrix formats.
5249 
5250 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5251 @*/
5252 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5253 {
5254   PetscFunctionBegin;
5255   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5256   PetscValidType(mat, 1);
5257   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5258   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5259 
5260   if (!mat->cmap->N) {
5261     PetscCall(VecSet(v, 0.0));
5262   } else {
5263     MatCheckPreallocated(mat, 1);
5264     PetscUseTypeMethod(mat, getrowsumabs, v);
5265   }
5266   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5267   PetscFunctionReturn(PETSC_SUCCESS);
5268 }
5269 
5270 /*@
5271   MatGetRowSum - Gets the sum of each row of the matrix
5272 
5273   Logically or Neighborhood Collective
5274 
5275   Input Parameter:
5276 . mat - the matrix
5277 
5278   Output Parameter:
5279 . v - the vector for storing the sum of rows
5280 
5281   Level: intermediate
5282 
5283   Note:
5284   This code is slow since it is not currently specialized for different formats
5285 
5286 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5287 @*/
5288 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5289 {
5290   Vec ones;
5291 
5292   PetscFunctionBegin;
5293   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5294   PetscValidType(mat, 1);
5295   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5296   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5297   MatCheckPreallocated(mat, 1);
5298   PetscCall(MatCreateVecs(mat, &ones, NULL));
5299   PetscCall(VecSet(ones, 1.));
5300   PetscCall(MatMult(mat, ones, v));
5301   PetscCall(VecDestroy(&ones));
5302   PetscFunctionReturn(PETSC_SUCCESS);
5303 }
5304 
5305 /*@
5306   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5307   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5308 
5309   Collective
5310 
5311   Input Parameter:
5312 . mat - the matrix to provide the transpose
5313 
5314   Output Parameter:
5315 . 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
5316 
5317   Level: advanced
5318 
5319   Note:
5320   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
5321   routine allows bypassing that call.
5322 
5323 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5324 @*/
5325 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5326 {
5327   MatParentState *rb = NULL;
5328 
5329   PetscFunctionBegin;
5330   PetscCall(PetscNew(&rb));
5331   rb->id    = ((PetscObject)mat)->id;
5332   rb->state = 0;
5333   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5334   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault));
5335   PetscFunctionReturn(PETSC_SUCCESS);
5336 }
5337 
5338 /*@
5339   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5340 
5341   Collective
5342 
5343   Input Parameters:
5344 + mat   - the matrix to transpose
5345 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5346 
5347   Output Parameter:
5348 . B - the transpose of the matrix
5349 
5350   Level: intermediate
5351 
5352   Notes:
5353   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5354 
5355   `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
5356   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5357 
5358   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.
5359 
5360   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5361   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5362 
5363   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5364 
5365   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5366 
5367 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5368           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5369 @*/
5370 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5371 {
5372   PetscContainer  rB = NULL;
5373   MatParentState *rb = NULL;
5374 
5375   PetscFunctionBegin;
5376   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5377   PetscValidType(mat, 1);
5378   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5379   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5380   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5381   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5382   MatCheckPreallocated(mat, 1);
5383   if (reuse == MAT_REUSE_MATRIX) {
5384     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5385     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5386     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5387     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5388     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5389   }
5390 
5391   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5392   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5393     PetscUseTypeMethod(mat, transpose, reuse, B);
5394     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5395   }
5396   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5397 
5398   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5399   if (reuse != MAT_INPLACE_MATRIX) {
5400     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5401     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5402     rb->state        = ((PetscObject)mat)->state;
5403     rb->nonzerostate = mat->nonzerostate;
5404   }
5405   PetscFunctionReturn(PETSC_SUCCESS);
5406 }
5407 
5408 /*@
5409   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5410 
5411   Collective
5412 
5413   Input Parameter:
5414 . A - the matrix to transpose
5415 
5416   Output Parameter:
5417 . 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
5418       numerical portion.
5419 
5420   Level: intermediate
5421 
5422   Note:
5423   This is not supported for many matrix types, use `MatTranspose()` in those cases
5424 
5425 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5426 @*/
5427 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5428 {
5429   PetscFunctionBegin;
5430   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5431   PetscValidType(A, 1);
5432   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5433   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5434   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5435   PetscUseTypeMethod(A, transposesymbolic, B);
5436   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5437 
5438   PetscCall(MatTransposeSetPrecursor(A, *B));
5439   PetscFunctionReturn(PETSC_SUCCESS);
5440 }
5441 
5442 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5443 {
5444   PetscContainer  rB;
5445   MatParentState *rb;
5446 
5447   PetscFunctionBegin;
5448   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5449   PetscValidType(A, 1);
5450   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5451   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5452   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5453   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5454   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5455   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5456   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5457   PetscFunctionReturn(PETSC_SUCCESS);
5458 }
5459 
5460 /*@
5461   MatIsTranspose - Test whether a matrix is another one's transpose,
5462   or its own, in which case it tests symmetry.
5463 
5464   Collective
5465 
5466   Input Parameters:
5467 + A   - the matrix to test
5468 . B   - the matrix to test against, this can equal the first parameter
5469 - tol - tolerance, differences between entries smaller than this are counted as zero
5470 
5471   Output Parameter:
5472 . flg - the result
5473 
5474   Level: intermediate
5475 
5476   Notes:
5477   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5478   test involves parallel copies of the block off-diagonal parts of the matrix.
5479 
5480 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5481 @*/
5482 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5483 {
5484   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5485 
5486   PetscFunctionBegin;
5487   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5488   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5489   PetscAssertPointer(flg, 4);
5490   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5491   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5492   *flg = PETSC_FALSE;
5493   if (f && g) {
5494     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5495     PetscCall((*f)(A, B, tol, flg));
5496   } else {
5497     MatType mattype;
5498 
5499     PetscCall(MatGetType(f ? B : A, &mattype));
5500     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5501   }
5502   PetscFunctionReturn(PETSC_SUCCESS);
5503 }
5504 
5505 /*@
5506   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5507 
5508   Collective
5509 
5510   Input Parameters:
5511 + mat   - the matrix to transpose and complex conjugate
5512 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5513 
5514   Output Parameter:
5515 . B - the Hermitian transpose
5516 
5517   Level: intermediate
5518 
5519 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5520 @*/
5521 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5522 {
5523   PetscFunctionBegin;
5524   PetscCall(MatTranspose(mat, reuse, B));
5525 #if defined(PETSC_USE_COMPLEX)
5526   PetscCall(MatConjugate(*B));
5527 #endif
5528   PetscFunctionReturn(PETSC_SUCCESS);
5529 }
5530 
5531 /*@
5532   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5533 
5534   Collective
5535 
5536   Input Parameters:
5537 + A   - the matrix to test
5538 . B   - the matrix to test against, this can equal the first parameter
5539 - tol - tolerance, differences between entries smaller than this are counted as zero
5540 
5541   Output Parameter:
5542 . flg - the result
5543 
5544   Level: intermediate
5545 
5546   Notes:
5547   Only available for `MATAIJ` matrices.
5548 
5549   The sequential algorithm
5550   has a running time of the order of the number of nonzeros; the parallel
5551   test involves parallel copies of the block off-diagonal parts of the matrix.
5552 
5553 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5554 @*/
5555 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5556 {
5557   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5558 
5559   PetscFunctionBegin;
5560   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5561   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5562   PetscAssertPointer(flg, 4);
5563   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5564   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5565   if (f && g) {
5566     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5567     PetscCall((*f)(A, B, tol, flg));
5568   }
5569   PetscFunctionReturn(PETSC_SUCCESS);
5570 }
5571 
5572 /*@
5573   MatPermute - Creates a new matrix with rows and columns permuted from the
5574   original.
5575 
5576   Collective
5577 
5578   Input Parameters:
5579 + mat - the matrix to permute
5580 . row - row permutation, each processor supplies only the permutation for its rows
5581 - col - column permutation, each processor supplies only the permutation for its columns
5582 
5583   Output Parameter:
5584 . B - the permuted matrix
5585 
5586   Level: advanced
5587 
5588   Note:
5589   The index sets map from row/col of permuted matrix to row/col of original matrix.
5590   The index sets should be on the same communicator as mat and have the same local sizes.
5591 
5592   Developer Note:
5593   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5594   exploit the fact that row and col are permutations, consider implementing the
5595   more general `MatCreateSubMatrix()` instead.
5596 
5597 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5598 @*/
5599 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5600 {
5601   PetscFunctionBegin;
5602   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5603   PetscValidType(mat, 1);
5604   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5605   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5606   PetscAssertPointer(B, 4);
5607   PetscCheckSameComm(mat, 1, row, 2);
5608   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5609   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5610   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5611   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5612   MatCheckPreallocated(mat, 1);
5613 
5614   if (mat->ops->permute) {
5615     PetscUseTypeMethod(mat, permute, row, col, B);
5616     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5617   } else {
5618     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5619   }
5620   PetscFunctionReturn(PETSC_SUCCESS);
5621 }
5622 
5623 /*@
5624   MatEqual - Compares two matrices.
5625 
5626   Collective
5627 
5628   Input Parameters:
5629 + A - the first matrix
5630 - B - the second matrix
5631 
5632   Output Parameter:
5633 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5634 
5635   Level: intermediate
5636 
5637   Note:
5638   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
5639   using several randomly created vectors, see `MatMultEqual()`.
5640 
5641 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()`
5642 @*/
5643 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5644 {
5645   PetscFunctionBegin;
5646   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5647   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5648   PetscValidType(A, 1);
5649   PetscValidType(B, 2);
5650   PetscAssertPointer(flg, 3);
5651   PetscCheckSameComm(A, 1, B, 2);
5652   MatCheckPreallocated(A, 1);
5653   MatCheckPreallocated(B, 2);
5654   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5655   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5656   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,
5657              B->cmap->N);
5658   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5659     PetscUseTypeMethod(A, equal, B, flg);
5660   } else {
5661     PetscCall(MatMultEqual(A, B, 10, flg));
5662   }
5663   PetscFunctionReturn(PETSC_SUCCESS);
5664 }
5665 
5666 /*@
5667   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5668   matrices that are stored as vectors.  Either of the two scaling
5669   matrices can be `NULL`.
5670 
5671   Collective
5672 
5673   Input Parameters:
5674 + mat - the matrix to be scaled
5675 . l   - the left scaling vector (or `NULL`)
5676 - r   - the right scaling vector (or `NULL`)
5677 
5678   Level: intermediate
5679 
5680   Note:
5681   `MatDiagonalScale()` computes $A = LAR$, where
5682   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5683   The L scales the rows of the matrix, the R scales the columns of the matrix.
5684 
5685 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5686 @*/
5687 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5688 {
5689   PetscFunctionBegin;
5690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5691   PetscValidType(mat, 1);
5692   if (l) {
5693     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5694     PetscCheckSameComm(mat, 1, l, 2);
5695   }
5696   if (r) {
5697     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5698     PetscCheckSameComm(mat, 1, r, 3);
5699   }
5700   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5701   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5702   MatCheckPreallocated(mat, 1);
5703   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5704 
5705   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5706   PetscUseTypeMethod(mat, diagonalscale, l, r);
5707   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5708   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5709   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5710   PetscFunctionReturn(PETSC_SUCCESS);
5711 }
5712 
5713 /*@
5714   MatScale - Scales all elements of a matrix by a given number.
5715 
5716   Logically Collective
5717 
5718   Input Parameters:
5719 + mat - the matrix to be scaled
5720 - a   - the scaling value
5721 
5722   Level: intermediate
5723 
5724 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5725 @*/
5726 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5727 {
5728   PetscFunctionBegin;
5729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5730   PetscValidType(mat, 1);
5731   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5732   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5733   PetscValidLogicalCollectiveScalar(mat, a, 2);
5734   MatCheckPreallocated(mat, 1);
5735 
5736   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5737   if (a != (PetscScalar)1.0) {
5738     PetscUseTypeMethod(mat, scale, a);
5739     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5740   }
5741   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5742   PetscFunctionReturn(PETSC_SUCCESS);
5743 }
5744 
5745 /*@
5746   MatNorm - Calculates various norms of a matrix.
5747 
5748   Collective
5749 
5750   Input Parameters:
5751 + mat  - the matrix
5752 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5753 
5754   Output Parameter:
5755 . nrm - the resulting norm
5756 
5757   Level: intermediate
5758 
5759 .seealso: [](ch_matrices), `Mat`
5760 @*/
5761 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5762 {
5763   PetscFunctionBegin;
5764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5765   PetscValidType(mat, 1);
5766   PetscAssertPointer(nrm, 3);
5767 
5768   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5769   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5770   MatCheckPreallocated(mat, 1);
5771 
5772   PetscUseTypeMethod(mat, norm, type, nrm);
5773   PetscFunctionReturn(PETSC_SUCCESS);
5774 }
5775 
5776 /*
5777      This variable is used to prevent counting of MatAssemblyBegin() that
5778    are called from within a MatAssemblyEnd().
5779 */
5780 static PetscInt MatAssemblyEnd_InUse = 0;
5781 /*@
5782   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5783   be called after completing all calls to `MatSetValues()`.
5784 
5785   Collective
5786 
5787   Input Parameters:
5788 + mat  - the matrix
5789 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5790 
5791   Level: beginner
5792 
5793   Notes:
5794   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5795   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5796 
5797   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5798   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5799   using the matrix.
5800 
5801   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5802   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
5803   a global collective operation requiring all processes that share the matrix.
5804 
5805   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5806   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5807   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5808 
5809 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5810 @*/
5811 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5812 {
5813   PetscFunctionBegin;
5814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5815   PetscValidType(mat, 1);
5816   MatCheckPreallocated(mat, 1);
5817   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5818   if (mat->assembled) {
5819     mat->was_assembled = PETSC_TRUE;
5820     mat->assembled     = PETSC_FALSE;
5821   }
5822 
5823   if (!MatAssemblyEnd_InUse) {
5824     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5825     PetscTryTypeMethod(mat, assemblybegin, type);
5826     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5827   } else PetscTryTypeMethod(mat, assemblybegin, type);
5828   PetscFunctionReturn(PETSC_SUCCESS);
5829 }
5830 
5831 /*@
5832   MatAssembled - Indicates if a matrix has been assembled and is ready for
5833   use; for example, in matrix-vector product.
5834 
5835   Not Collective
5836 
5837   Input Parameter:
5838 . mat - the matrix
5839 
5840   Output Parameter:
5841 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5842 
5843   Level: advanced
5844 
5845 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5846 @*/
5847 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5848 {
5849   PetscFunctionBegin;
5850   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5851   PetscAssertPointer(assembled, 2);
5852   *assembled = mat->assembled;
5853   PetscFunctionReturn(PETSC_SUCCESS);
5854 }
5855 
5856 /*@
5857   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5858   be called after `MatAssemblyBegin()`.
5859 
5860   Collective
5861 
5862   Input Parameters:
5863 + mat  - the matrix
5864 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5865 
5866   Options Database Keys:
5867 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5868 . -mat_view ::ascii_info_detail      - Prints more detailed info
5869 . -mat_view                          - Prints matrix in ASCII format
5870 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5871 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5872 . -display <name>                    - Sets display name (default is host)
5873 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5874 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5875 . -viewer_socket_machine <machine>   - Machine to use for socket
5876 . -viewer_socket_port <port>         - Port number to use for socket
5877 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5878 
5879   Level: beginner
5880 
5881 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5882 @*/
5883 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5884 {
5885   static PetscInt inassm = 0;
5886   PetscBool       flg    = PETSC_FALSE;
5887 
5888   PetscFunctionBegin;
5889   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5890   PetscValidType(mat, 1);
5891 
5892   inassm++;
5893   MatAssemblyEnd_InUse++;
5894   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5895     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5896     PetscTryTypeMethod(mat, assemblyend, type);
5897     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5898   } else PetscTryTypeMethod(mat, assemblyend, type);
5899 
5900   /* Flush assembly is not a true assembly */
5901   if (type != MAT_FLUSH_ASSEMBLY) {
5902     if (mat->num_ass) {
5903       if (!mat->symmetry_eternal) {
5904         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5905         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5906       }
5907       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5908       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5909     }
5910     mat->num_ass++;
5911     mat->assembled        = PETSC_TRUE;
5912     mat->ass_nonzerostate = mat->nonzerostate;
5913   }
5914 
5915   mat->insertmode = NOT_SET_VALUES;
5916   MatAssemblyEnd_InUse--;
5917   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5918   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5919     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5920 
5921     if (mat->checksymmetryonassembly) {
5922       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5923       if (flg) {
5924         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5925       } else {
5926         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5927       }
5928     }
5929     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5930   }
5931   inassm--;
5932   PetscFunctionReturn(PETSC_SUCCESS);
5933 }
5934 
5935 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5936 /*@
5937   MatSetOption - Sets a parameter option for a matrix. Some options
5938   may be specific to certain storage formats.  Some options
5939   determine how values will be inserted (or added). Sorted,
5940   row-oriented input will generally assemble the fastest. The default
5941   is row-oriented.
5942 
5943   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5944 
5945   Input Parameters:
5946 + mat - the matrix
5947 . op  - the option, one of those listed below (and possibly others),
5948 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5949 
5950   Options Describing Matrix Structure:
5951 + `MAT_SPD`                         - symmetric positive definite
5952 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5953 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5954 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5955 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5956 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5957 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5958 
5959    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5960    do not need to be computed (usually at a high cost)
5961 
5962    Options For Use with `MatSetValues()`:
5963    Insert a logically dense subblock, which can be
5964 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5965 
5966    These options reflect the data you pass in with `MatSetValues()`; it has
5967    nothing to do with how the data is stored internally in the matrix
5968    data structure.
5969 
5970    When (re)assembling a matrix, we can restrict the input for
5971    efficiency/debugging purposes.  These options include
5972 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5973 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5974 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5975 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5976 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5977 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5978         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5979         performance for very large process counts.
5980 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5981         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5982         functions, instead sending only neighbor messages.
5983 
5984   Level: intermediate
5985 
5986   Notes:
5987   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5988 
5989   Some options are relevant only for particular matrix types and
5990   are thus ignored by others.  Other options are not supported by
5991   certain matrix types and will generate an error message if set.
5992 
5993   If using Fortran to compute a matrix, one may need to
5994   use the column-oriented option (or convert to the row-oriented
5995   format).
5996 
5997   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5998   that would generate a new entry in the nonzero structure is instead
5999   ignored.  Thus, if memory has not already been allocated for this particular
6000   data, then the insertion is ignored. For dense matrices, in which
6001   the entire array is allocated, no entries are ever ignored.
6002   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6003 
6004   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
6005   that would generate a new entry in the nonzero structure instead produces
6006   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
6007 
6008   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
6009   that would generate a new entry that has not been preallocated will
6010   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
6011   only.) This is a useful flag when debugging matrix memory preallocation.
6012   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6013 
6014   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6015   other processors should be dropped, rather than stashed.
6016   This is useful if you know that the "owning" processor is also
6017   always generating the correct matrix entries, so that PETSc need
6018   not transfer duplicate entries generated on another processor.
6019 
6020   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6021   searches during matrix assembly. When this flag is set, the hash table
6022   is created during the first matrix assembly. This hash table is
6023   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6024   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6025   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6026   supported by `MATMPIBAIJ` format only.
6027 
6028   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6029   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6030 
6031   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6032   a zero location in the matrix
6033 
6034   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6035 
6036   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6037   zero row routines and thus improves performance for very large process counts.
6038 
6039   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6040   part of the matrix (since they should match the upper triangular part).
6041 
6042   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6043   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6044   with finite difference schemes with non-periodic boundary conditions.
6045 
6046   Developer Note:
6047   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6048   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6049   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6050   not changed.
6051 
6052 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6053 @*/
6054 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6055 {
6056   PetscFunctionBegin;
6057   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6058   if (op > 0) {
6059     PetscValidLogicalCollectiveEnum(mat, op, 2);
6060     PetscValidLogicalCollectiveBool(mat, flg, 3);
6061   }
6062 
6063   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);
6064 
6065   switch (op) {
6066   case MAT_FORCE_DIAGONAL_ENTRIES:
6067     mat->force_diagonals = flg;
6068     PetscFunctionReturn(PETSC_SUCCESS);
6069   case MAT_NO_OFF_PROC_ENTRIES:
6070     mat->nooffprocentries = flg;
6071     PetscFunctionReturn(PETSC_SUCCESS);
6072   case MAT_SUBSET_OFF_PROC_ENTRIES:
6073     mat->assembly_subset = flg;
6074     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6075 #if !defined(PETSC_HAVE_MPIUNI)
6076       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6077 #endif
6078       mat->stash.first_assembly_done = PETSC_FALSE;
6079     }
6080     PetscFunctionReturn(PETSC_SUCCESS);
6081   case MAT_NO_OFF_PROC_ZERO_ROWS:
6082     mat->nooffproczerorows = flg;
6083     PetscFunctionReturn(PETSC_SUCCESS);
6084   case MAT_SPD:
6085     if (flg) {
6086       mat->spd                    = PETSC_BOOL3_TRUE;
6087       mat->symmetric              = PETSC_BOOL3_TRUE;
6088       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6089     } else {
6090       mat->spd = PETSC_BOOL3_FALSE;
6091     }
6092     break;
6093   case MAT_SYMMETRIC:
6094     mat->symmetric = PetscBoolToBool3(flg);
6095     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6096 #if !defined(PETSC_USE_COMPLEX)
6097     mat->hermitian = PetscBoolToBool3(flg);
6098 #endif
6099     break;
6100   case MAT_HERMITIAN:
6101     mat->hermitian = PetscBoolToBool3(flg);
6102     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6103 #if !defined(PETSC_USE_COMPLEX)
6104     mat->symmetric = PetscBoolToBool3(flg);
6105 #endif
6106     break;
6107   case MAT_STRUCTURALLY_SYMMETRIC:
6108     mat->structurally_symmetric = PetscBoolToBool3(flg);
6109     break;
6110   case MAT_SYMMETRY_ETERNAL:
6111     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");
6112     mat->symmetry_eternal = flg;
6113     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6114     break;
6115   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6116     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");
6117     mat->structural_symmetry_eternal = flg;
6118     break;
6119   case MAT_SPD_ETERNAL:
6120     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");
6121     mat->spd_eternal = flg;
6122     if (flg) {
6123       mat->structural_symmetry_eternal = PETSC_TRUE;
6124       mat->symmetry_eternal            = PETSC_TRUE;
6125     }
6126     break;
6127   case MAT_STRUCTURE_ONLY:
6128     mat->structure_only = flg;
6129     break;
6130   case MAT_SORTED_FULL:
6131     mat->sortedfull = flg;
6132     break;
6133   default:
6134     break;
6135   }
6136   PetscTryTypeMethod(mat, setoption, op, flg);
6137   PetscFunctionReturn(PETSC_SUCCESS);
6138 }
6139 
6140 /*@
6141   MatGetOption - Gets a parameter option that has been set for a matrix.
6142 
6143   Logically Collective
6144 
6145   Input Parameters:
6146 + mat - the matrix
6147 - op  - the option, this only responds to certain options, check the code for which ones
6148 
6149   Output Parameter:
6150 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6151 
6152   Level: intermediate
6153 
6154   Notes:
6155   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6156 
6157   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6158   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6159 
6160 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6161     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6162 @*/
6163 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6164 {
6165   PetscFunctionBegin;
6166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6167   PetscValidType(mat, 1);
6168 
6169   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);
6170   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()");
6171 
6172   switch (op) {
6173   case MAT_NO_OFF_PROC_ENTRIES:
6174     *flg = mat->nooffprocentries;
6175     break;
6176   case MAT_NO_OFF_PROC_ZERO_ROWS:
6177     *flg = mat->nooffproczerorows;
6178     break;
6179   case MAT_SYMMETRIC:
6180     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6181     break;
6182   case MAT_HERMITIAN:
6183     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6184     break;
6185   case MAT_STRUCTURALLY_SYMMETRIC:
6186     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6187     break;
6188   case MAT_SPD:
6189     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6190     break;
6191   case MAT_SYMMETRY_ETERNAL:
6192     *flg = mat->symmetry_eternal;
6193     break;
6194   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6195     *flg = mat->symmetry_eternal;
6196     break;
6197   default:
6198     break;
6199   }
6200   PetscFunctionReturn(PETSC_SUCCESS);
6201 }
6202 
6203 /*@
6204   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6205   this routine retains the old nonzero structure.
6206 
6207   Logically Collective
6208 
6209   Input Parameter:
6210 . mat - the matrix
6211 
6212   Level: intermediate
6213 
6214   Note:
6215   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.
6216   See the Performance chapter of the users manual for information on preallocating matrices.
6217 
6218 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6219 @*/
6220 PetscErrorCode MatZeroEntries(Mat mat)
6221 {
6222   PetscFunctionBegin;
6223   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6224   PetscValidType(mat, 1);
6225   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6226   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");
6227   MatCheckPreallocated(mat, 1);
6228 
6229   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6230   PetscUseTypeMethod(mat, zeroentries);
6231   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6232   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6233   PetscFunctionReturn(PETSC_SUCCESS);
6234 }
6235 
6236 /*@
6237   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6238   of a set of rows and columns of a matrix.
6239 
6240   Collective
6241 
6242   Input Parameters:
6243 + mat     - the matrix
6244 . numRows - the number of rows/columns to zero
6245 . rows    - the global row indices
6246 . diag    - value put in the diagonal of the eliminated rows
6247 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6248 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6249 
6250   Level: intermediate
6251 
6252   Notes:
6253   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6254 
6255   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6256   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
6257 
6258   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6259   Krylov method to take advantage of the known solution on the zeroed rows.
6260 
6261   For the parallel case, all processes that share the matrix (i.e.,
6262   those in the communicator used for matrix creation) MUST call this
6263   routine, regardless of whether any rows being zeroed are owned by
6264   them.
6265 
6266   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6267   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
6268   missing.
6269 
6270   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6271   list only rows local to itself).
6272 
6273   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6274 
6275 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6276           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6277 @*/
6278 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6279 {
6280   PetscFunctionBegin;
6281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6282   PetscValidType(mat, 1);
6283   if (numRows) PetscAssertPointer(rows, 3);
6284   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6285   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6286   MatCheckPreallocated(mat, 1);
6287 
6288   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6289   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6290   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6291   PetscFunctionReturn(PETSC_SUCCESS);
6292 }
6293 
6294 /*@
6295   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6296   of a set of rows and columns of a matrix.
6297 
6298   Collective
6299 
6300   Input Parameters:
6301 + mat  - the matrix
6302 . is   - the rows to zero
6303 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6304 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6305 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6306 
6307   Level: intermediate
6308 
6309   Note:
6310   See `MatZeroRowsColumns()` for details on how this routine operates.
6311 
6312 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6313           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6314 @*/
6315 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6316 {
6317   PetscInt        numRows;
6318   const PetscInt *rows;
6319 
6320   PetscFunctionBegin;
6321   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6322   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6323   PetscValidType(mat, 1);
6324   PetscValidType(is, 2);
6325   PetscCall(ISGetLocalSize(is, &numRows));
6326   PetscCall(ISGetIndices(is, &rows));
6327   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6328   PetscCall(ISRestoreIndices(is, &rows));
6329   PetscFunctionReturn(PETSC_SUCCESS);
6330 }
6331 
6332 /*@
6333   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6334   of a set of rows of a matrix.
6335 
6336   Collective
6337 
6338   Input Parameters:
6339 + mat     - the matrix
6340 . numRows - the number of rows to zero
6341 . rows    - the global row indices
6342 . diag    - value put in the diagonal of the zeroed rows
6343 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6344 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6345 
6346   Level: intermediate
6347 
6348   Notes:
6349   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6350 
6351   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6352 
6353   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6354   Krylov method to take advantage of the known solution on the zeroed rows.
6355 
6356   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)
6357   from the matrix.
6358 
6359   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6360   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6361   formats this does not alter the nonzero structure.
6362 
6363   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6364   of the matrix is not changed the values are
6365   merely zeroed.
6366 
6367   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6368   formats can optionally remove the main diagonal entry from the
6369   nonzero structure as well, by passing 0.0 as the final argument).
6370 
6371   For the parallel case, all processes that share the matrix (i.e.,
6372   those in the communicator used for matrix creation) MUST call this
6373   routine, regardless of whether any rows being zeroed are owned by
6374   them.
6375 
6376   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6377   list only rows local to itself).
6378 
6379   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6380   owns that are to be zeroed. This saves a global synchronization in the implementation.
6381 
6382 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6383           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6384 @*/
6385 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6386 {
6387   PetscFunctionBegin;
6388   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6389   PetscValidType(mat, 1);
6390   if (numRows) PetscAssertPointer(rows, 3);
6391   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6392   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6393   MatCheckPreallocated(mat, 1);
6394 
6395   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6396   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6397   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6398   PetscFunctionReturn(PETSC_SUCCESS);
6399 }
6400 
6401 /*@
6402   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6403   of a set of rows of a matrix indicated by an `IS`
6404 
6405   Collective
6406 
6407   Input Parameters:
6408 + mat  - the matrix
6409 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6410 . diag - value put in all diagonals of eliminated rows
6411 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6412 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6413 
6414   Level: intermediate
6415 
6416   Note:
6417   See `MatZeroRows()` for details on how this routine operates.
6418 
6419 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6420           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6421 @*/
6422 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6423 {
6424   PetscInt        numRows = 0;
6425   const PetscInt *rows    = NULL;
6426 
6427   PetscFunctionBegin;
6428   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6429   PetscValidType(mat, 1);
6430   if (is) {
6431     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6432     PetscCall(ISGetLocalSize(is, &numRows));
6433     PetscCall(ISGetIndices(is, &rows));
6434   }
6435   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6436   if (is) PetscCall(ISRestoreIndices(is, &rows));
6437   PetscFunctionReturn(PETSC_SUCCESS);
6438 }
6439 
6440 /*@
6441   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6442   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6443 
6444   Collective
6445 
6446   Input Parameters:
6447 + mat     - the matrix
6448 . numRows - the number of rows to remove
6449 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6450 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6451 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6452 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6453 
6454   Level: intermediate
6455 
6456   Notes:
6457   See `MatZeroRows()` for details on how this routine operates.
6458 
6459   The grid coordinates are across the entire grid, not just the local portion
6460 
6461   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6462   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6463   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6464   `DM_BOUNDARY_PERIODIC` boundary type.
6465 
6466   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
6467   a single value per point) you can skip filling those indices.
6468 
6469   Fortran Note:
6470   `idxm` and `idxn` should be declared as
6471 .vb
6472     MatStencil idxm(4, m)
6473 .ve
6474   and the values inserted using
6475 .vb
6476     idxm(MatStencil_i, 1) = i
6477     idxm(MatStencil_j, 1) = j
6478     idxm(MatStencil_k, 1) = k
6479     idxm(MatStencil_c, 1) = c
6480    etc
6481 .ve
6482 
6483 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6484           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6485 @*/
6486 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6487 {
6488   PetscInt  dim    = mat->stencil.dim;
6489   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6490   PetscInt *dims   = mat->stencil.dims + 1;
6491   PetscInt *starts = mat->stencil.starts;
6492   PetscInt *dxm    = (PetscInt *)rows;
6493   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6494 
6495   PetscFunctionBegin;
6496   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6497   PetscValidType(mat, 1);
6498   if (numRows) PetscAssertPointer(rows, 3);
6499 
6500   PetscCall(PetscMalloc1(numRows, &jdxm));
6501   for (i = 0; i < numRows; ++i) {
6502     /* Skip unused dimensions (they are ordered k, j, i, c) */
6503     for (j = 0; j < 3 - sdim; ++j) dxm++;
6504     /* Local index in X dir */
6505     tmp = *dxm++ - starts[0];
6506     /* Loop over remaining dimensions */
6507     for (j = 0; j < dim - 1; ++j) {
6508       /* If nonlocal, set index to be negative */
6509       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6510       /* Update local index */
6511       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6512     }
6513     /* Skip component slot if necessary */
6514     if (mat->stencil.noc) dxm++;
6515     /* Local row number */
6516     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6517   }
6518   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6519   PetscCall(PetscFree(jdxm));
6520   PetscFunctionReturn(PETSC_SUCCESS);
6521 }
6522 
6523 /*@
6524   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6525   of a set of rows and columns of a matrix.
6526 
6527   Collective
6528 
6529   Input Parameters:
6530 + mat     - the matrix
6531 . numRows - the number of rows/columns to remove
6532 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6533 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6534 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6535 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6536 
6537   Level: intermediate
6538 
6539   Notes:
6540   See `MatZeroRowsColumns()` for details on how this routine operates.
6541 
6542   The grid coordinates are across the entire grid, not just the local portion
6543 
6544   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6545   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6546   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6547   `DM_BOUNDARY_PERIODIC` boundary type.
6548 
6549   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
6550   a single value per point) you can skip filling those indices.
6551 
6552   Fortran Note:
6553   `idxm` and `idxn` should be declared as
6554 .vb
6555     MatStencil idxm(4, m)
6556 .ve
6557   and the values inserted using
6558 .vb
6559     idxm(MatStencil_i, 1) = i
6560     idxm(MatStencil_j, 1) = j
6561     idxm(MatStencil_k, 1) = k
6562     idxm(MatStencil_c, 1) = c
6563     etc
6564 .ve
6565 
6566 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6567           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6568 @*/
6569 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6570 {
6571   PetscInt  dim    = mat->stencil.dim;
6572   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6573   PetscInt *dims   = mat->stencil.dims + 1;
6574   PetscInt *starts = mat->stencil.starts;
6575   PetscInt *dxm    = (PetscInt *)rows;
6576   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6577 
6578   PetscFunctionBegin;
6579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6580   PetscValidType(mat, 1);
6581   if (numRows) PetscAssertPointer(rows, 3);
6582 
6583   PetscCall(PetscMalloc1(numRows, &jdxm));
6584   for (i = 0; i < numRows; ++i) {
6585     /* Skip unused dimensions (they are ordered k, j, i, c) */
6586     for (j = 0; j < 3 - sdim; ++j) dxm++;
6587     /* Local index in X dir */
6588     tmp = *dxm++ - starts[0];
6589     /* Loop over remaining dimensions */
6590     for (j = 0; j < dim - 1; ++j) {
6591       /* If nonlocal, set index to be negative */
6592       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6593       /* Update local index */
6594       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6595     }
6596     /* Skip component slot if necessary */
6597     if (mat->stencil.noc) dxm++;
6598     /* Local row number */
6599     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6600   }
6601   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6602   PetscCall(PetscFree(jdxm));
6603   PetscFunctionReturn(PETSC_SUCCESS);
6604 }
6605 
6606 /*@
6607   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6608   of a set of rows of a matrix; using local numbering of rows.
6609 
6610   Collective
6611 
6612   Input Parameters:
6613 + mat     - the matrix
6614 . numRows - the number of rows to remove
6615 . rows    - the local row indices
6616 . diag    - value put in all diagonals of eliminated rows
6617 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6618 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6619 
6620   Level: intermediate
6621 
6622   Notes:
6623   Before calling `MatZeroRowsLocal()`, the user must first set the
6624   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6625 
6626   See `MatZeroRows()` for details on how this routine operates.
6627 
6628 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6629           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6630 @*/
6631 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6632 {
6633   PetscFunctionBegin;
6634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6635   PetscValidType(mat, 1);
6636   if (numRows) PetscAssertPointer(rows, 3);
6637   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6638   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6639   MatCheckPreallocated(mat, 1);
6640 
6641   if (mat->ops->zerorowslocal) {
6642     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6643   } else {
6644     IS              is, newis;
6645     const PetscInt *newRows;
6646 
6647     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6648     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6649     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6650     PetscCall(ISGetIndices(newis, &newRows));
6651     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6652     PetscCall(ISRestoreIndices(newis, &newRows));
6653     PetscCall(ISDestroy(&newis));
6654     PetscCall(ISDestroy(&is));
6655   }
6656   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6657   PetscFunctionReturn(PETSC_SUCCESS);
6658 }
6659 
6660 /*@
6661   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6662   of a set of rows of a matrix; using local numbering of rows.
6663 
6664   Collective
6665 
6666   Input Parameters:
6667 + mat  - the matrix
6668 . is   - index set of rows to remove
6669 . diag - value put in all diagonals of eliminated rows
6670 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6671 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6672 
6673   Level: intermediate
6674 
6675   Notes:
6676   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6677   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6678 
6679   See `MatZeroRows()` for details on how this routine operates.
6680 
6681 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6682           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6683 @*/
6684 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6685 {
6686   PetscInt        numRows;
6687   const PetscInt *rows;
6688 
6689   PetscFunctionBegin;
6690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6691   PetscValidType(mat, 1);
6692   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6693   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6694   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6695   MatCheckPreallocated(mat, 1);
6696 
6697   PetscCall(ISGetLocalSize(is, &numRows));
6698   PetscCall(ISGetIndices(is, &rows));
6699   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6700   PetscCall(ISRestoreIndices(is, &rows));
6701   PetscFunctionReturn(PETSC_SUCCESS);
6702 }
6703 
6704 /*@
6705   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6706   of a set of rows and columns of a matrix; using local numbering of rows.
6707 
6708   Collective
6709 
6710   Input Parameters:
6711 + mat     - the matrix
6712 . numRows - the number of rows to remove
6713 . rows    - the global row indices
6714 . diag    - value put in all diagonals of eliminated rows
6715 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6716 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6717 
6718   Level: intermediate
6719 
6720   Notes:
6721   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6722   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6723 
6724   See `MatZeroRowsColumns()` for details on how this routine operates.
6725 
6726 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6727           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6728 @*/
6729 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6730 {
6731   IS              is, newis;
6732   const PetscInt *newRows;
6733 
6734   PetscFunctionBegin;
6735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6736   PetscValidType(mat, 1);
6737   if (numRows) PetscAssertPointer(rows, 3);
6738   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6739   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6740   MatCheckPreallocated(mat, 1);
6741 
6742   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6743   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6744   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6745   PetscCall(ISGetIndices(newis, &newRows));
6746   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6747   PetscCall(ISRestoreIndices(newis, &newRows));
6748   PetscCall(ISDestroy(&newis));
6749   PetscCall(ISDestroy(&is));
6750   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6751   PetscFunctionReturn(PETSC_SUCCESS);
6752 }
6753 
6754 /*@
6755   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6756   of a set of rows and columns of a matrix; using local numbering of rows.
6757 
6758   Collective
6759 
6760   Input Parameters:
6761 + mat  - the matrix
6762 . is   - index set of rows to remove
6763 . diag - value put in all diagonals of eliminated rows
6764 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6765 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6766 
6767   Level: intermediate
6768 
6769   Notes:
6770   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6771   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6772 
6773   See `MatZeroRowsColumns()` for details on how this routine operates.
6774 
6775 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6776           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6777 @*/
6778 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6779 {
6780   PetscInt        numRows;
6781   const PetscInt *rows;
6782 
6783   PetscFunctionBegin;
6784   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6785   PetscValidType(mat, 1);
6786   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6787   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6788   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6789   MatCheckPreallocated(mat, 1);
6790 
6791   PetscCall(ISGetLocalSize(is, &numRows));
6792   PetscCall(ISGetIndices(is, &rows));
6793   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6794   PetscCall(ISRestoreIndices(is, &rows));
6795   PetscFunctionReturn(PETSC_SUCCESS);
6796 }
6797 
6798 /*@
6799   MatGetSize - Returns the numbers of rows and columns in a matrix.
6800 
6801   Not Collective
6802 
6803   Input Parameter:
6804 . mat - the matrix
6805 
6806   Output Parameters:
6807 + m - the number of global rows
6808 - n - the number of global columns
6809 
6810   Level: beginner
6811 
6812   Note:
6813   Both output parameters can be `NULL` on input.
6814 
6815 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6816 @*/
6817 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6818 {
6819   PetscFunctionBegin;
6820   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6821   if (m) *m = mat->rmap->N;
6822   if (n) *n = mat->cmap->N;
6823   PetscFunctionReturn(PETSC_SUCCESS);
6824 }
6825 
6826 /*@
6827   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6828   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6829 
6830   Not Collective
6831 
6832   Input Parameter:
6833 . mat - the matrix
6834 
6835   Output Parameters:
6836 + m - the number of local rows, use `NULL` to not obtain this value
6837 - n - the number of local columns, use `NULL` to not obtain this value
6838 
6839   Level: beginner
6840 
6841 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6842 @*/
6843 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6844 {
6845   PetscFunctionBegin;
6846   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6847   if (m) PetscAssertPointer(m, 2);
6848   if (n) PetscAssertPointer(n, 3);
6849   if (m) *m = mat->rmap->n;
6850   if (n) *n = mat->cmap->n;
6851   PetscFunctionReturn(PETSC_SUCCESS);
6852 }
6853 
6854 /*@
6855   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6856   vector one multiplies this matrix by that are owned by this processor.
6857 
6858   Not Collective, unless matrix has not been allocated, then collective
6859 
6860   Input Parameter:
6861 . mat - the matrix
6862 
6863   Output Parameters:
6864 + m - the global index of the first local column, use `NULL` to not obtain this value
6865 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6866 
6867   Level: developer
6868 
6869   Notes:
6870   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6871 
6872   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6873   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6874 
6875   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6876   the local values in the matrix.
6877 
6878   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6879   Layouts](sec_matlayout) for details on matrix layouts.
6880 
6881 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6882           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6883 @*/
6884 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6885 {
6886   PetscFunctionBegin;
6887   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6888   PetscValidType(mat, 1);
6889   if (m) PetscAssertPointer(m, 2);
6890   if (n) PetscAssertPointer(n, 3);
6891   MatCheckPreallocated(mat, 1);
6892   if (m) *m = mat->cmap->rstart;
6893   if (n) *n = mat->cmap->rend;
6894   PetscFunctionReturn(PETSC_SUCCESS);
6895 }
6896 
6897 /*@
6898   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6899   this MPI process.
6900 
6901   Not Collective
6902 
6903   Input Parameter:
6904 . mat - the matrix
6905 
6906   Output Parameters:
6907 + m - the global index of the first local row, use `NULL` to not obtain this value
6908 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6909 
6910   Level: beginner
6911 
6912   Notes:
6913   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6914 
6915   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6916   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6917 
6918   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6919   the local values in the matrix.
6920 
6921   The high argument is one more than the last element stored locally.
6922 
6923   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6924   would contain the result of a matrix vector product with this matrix. See [Matrix
6925   Layouts](sec_matlayout) for details on matrix layouts.
6926 
6927 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6928           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6929 @*/
6930 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6931 {
6932   PetscFunctionBegin;
6933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6934   PetscValidType(mat, 1);
6935   if (m) PetscAssertPointer(m, 2);
6936   if (n) PetscAssertPointer(n, 3);
6937   MatCheckPreallocated(mat, 1);
6938   if (m) *m = mat->rmap->rstart;
6939   if (n) *n = mat->rmap->rend;
6940   PetscFunctionReturn(PETSC_SUCCESS);
6941 }
6942 
6943 /*@C
6944   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6945   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6946 
6947   Not Collective, unless matrix has not been allocated
6948 
6949   Input Parameter:
6950 . mat - the matrix
6951 
6952   Output Parameter:
6953 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6954            where `size` is the number of MPI processes used by `mat`
6955 
6956   Level: beginner
6957 
6958   Notes:
6959   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6960 
6961   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6962   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6963 
6964   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6965   the local values in the matrix.
6966 
6967   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6968   would contain the result of a matrix vector product with this matrix. See [Matrix
6969   Layouts](sec_matlayout) for details on matrix layouts.
6970 
6971 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6972           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6973           `DMDAGetGhostCorners()`, `DM`
6974 @*/
6975 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6976 {
6977   PetscFunctionBegin;
6978   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6979   PetscValidType(mat, 1);
6980   MatCheckPreallocated(mat, 1);
6981   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6982   PetscFunctionReturn(PETSC_SUCCESS);
6983 }
6984 
6985 /*@C
6986   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6987   vector one multiplies this vector by that are owned by each processor.
6988 
6989   Not Collective, unless matrix has not been allocated
6990 
6991   Input Parameter:
6992 . mat - the matrix
6993 
6994   Output Parameter:
6995 . ranges - start of each processors portion plus one more than the total length at the end
6996 
6997   Level: beginner
6998 
6999   Notes:
7000   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
7001 
7002   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
7003   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
7004 
7005   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
7006   the local values in the matrix.
7007 
7008   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
7009   Layouts](sec_matlayout) for details on matrix layouts.
7010 
7011 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
7012           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
7013           `DMDAGetGhostCorners()`, `DM`
7014 @*/
7015 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
7016 {
7017   PetscFunctionBegin;
7018   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7019   PetscValidType(mat, 1);
7020   MatCheckPreallocated(mat, 1);
7021   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7022   PetscFunctionReturn(PETSC_SUCCESS);
7023 }
7024 
7025 /*@
7026   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7027 
7028   Not Collective
7029 
7030   Input Parameter:
7031 . A - matrix
7032 
7033   Output Parameters:
7034 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7035 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7036 
7037   Level: intermediate
7038 
7039   Note:
7040   You should call `ISDestroy()` on the returned `IS`
7041 
7042   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7043   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7044   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7045   details on matrix layouts.
7046 
7047 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7048 @*/
7049 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7050 {
7051   PetscErrorCode (*f)(Mat, IS *, IS *);
7052 
7053   PetscFunctionBegin;
7054   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7055   PetscValidType(A, 1);
7056   MatCheckPreallocated(A, 1);
7057   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7058   if (f) {
7059     PetscCall((*f)(A, rows, cols));
7060   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7061     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7062     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7063   }
7064   PetscFunctionReturn(PETSC_SUCCESS);
7065 }
7066 
7067 /*@
7068   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7069   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7070   to complete the factorization.
7071 
7072   Collective
7073 
7074   Input Parameters:
7075 + fact - the factorized matrix obtained with `MatGetFactor()`
7076 . mat  - the matrix
7077 . row  - row permutation
7078 . col  - column permutation
7079 - info - structure containing
7080 .vb
7081       levels - number of levels of fill.
7082       expected fill - as ratio of original fill.
7083       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7084                 missing diagonal entries)
7085 .ve
7086 
7087   Level: developer
7088 
7089   Notes:
7090   See [Matrix Factorization](sec_matfactor) for additional information.
7091 
7092   Most users should employ the `KSP` interface for linear solvers
7093   instead of working directly with matrix algebra routines such as this.
7094   See, e.g., `KSPCreate()`.
7095 
7096   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7097 
7098   Developer Note:
7099   The Fortran interface is not autogenerated as the
7100   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7101 
7102 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7103           `MatGetOrdering()`, `MatFactorInfo`
7104 @*/
7105 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7106 {
7107   PetscFunctionBegin;
7108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7109   PetscValidType(mat, 2);
7110   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7111   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7112   PetscAssertPointer(info, 5);
7113   PetscAssertPointer(fact, 1);
7114   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7115   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7116   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7117   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7118   MatCheckPreallocated(mat, 2);
7119 
7120   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7121   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7122   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7123   PetscFunctionReturn(PETSC_SUCCESS);
7124 }
7125 
7126 /*@
7127   MatICCFactorSymbolic - Performs symbolic incomplete
7128   Cholesky factorization for a symmetric matrix.  Use
7129   `MatCholeskyFactorNumeric()` to complete the factorization.
7130 
7131   Collective
7132 
7133   Input Parameters:
7134 + fact - the factorized matrix obtained with `MatGetFactor()`
7135 . mat  - the matrix to be factored
7136 . perm - row and column permutation
7137 - info - structure containing
7138 .vb
7139       levels - number of levels of fill.
7140       expected fill - as ratio of original fill.
7141 .ve
7142 
7143   Level: developer
7144 
7145   Notes:
7146   Most users should employ the `KSP` interface for linear solvers
7147   instead of working directly with matrix algebra routines such as this.
7148   See, e.g., `KSPCreate()`.
7149 
7150   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7151 
7152   Developer Note:
7153   The Fortran interface is not autogenerated as the
7154   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7155 
7156 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7157 @*/
7158 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7159 {
7160   PetscFunctionBegin;
7161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7162   PetscValidType(mat, 2);
7163   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7164   PetscAssertPointer(info, 4);
7165   PetscAssertPointer(fact, 1);
7166   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7167   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7168   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7169   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7170   MatCheckPreallocated(mat, 2);
7171 
7172   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7173   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7174   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7175   PetscFunctionReturn(PETSC_SUCCESS);
7176 }
7177 
7178 /*@C
7179   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7180   points to an array of valid matrices, they may be reused to store the new
7181   submatrices.
7182 
7183   Collective
7184 
7185   Input Parameters:
7186 + mat   - the matrix
7187 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7188 . irow  - index set of rows to extract
7189 . icol  - index set of columns to extract
7190 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7191 
7192   Output Parameter:
7193 . submat - the array of submatrices
7194 
7195   Level: advanced
7196 
7197   Notes:
7198   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7199   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7200   to extract a parallel submatrix.
7201 
7202   Some matrix types place restrictions on the row and column
7203   indices, such as that they be sorted or that they be equal to each other.
7204 
7205   The index sets may not have duplicate entries.
7206 
7207   When extracting submatrices from a parallel matrix, each processor can
7208   form a different submatrix by setting the rows and columns of its
7209   individual index sets according to the local submatrix desired.
7210 
7211   When finished using the submatrices, the user should destroy
7212   them with `MatDestroySubMatrices()`.
7213 
7214   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7215   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7216 
7217   This routine creates the matrices in submat; you should NOT create them before
7218   calling it. It also allocates the array of matrix pointers submat.
7219 
7220   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7221   request one row/column in a block, they must request all rows/columns that are in
7222   that block. For example, if the block size is 2 you cannot request just row 0 and
7223   column 0.
7224 
7225   Fortran Note:
7226 .vb
7227   Mat, pointer :: submat(:)
7228 .ve
7229 
7230 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7231 @*/
7232 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7233 {
7234   PetscInt  i;
7235   PetscBool eq;
7236 
7237   PetscFunctionBegin;
7238   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7239   PetscValidType(mat, 1);
7240   if (n) {
7241     PetscAssertPointer(irow, 3);
7242     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7243     PetscAssertPointer(icol, 4);
7244     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7245   }
7246   PetscAssertPointer(submat, 6);
7247   if (n && scall == MAT_REUSE_MATRIX) {
7248     PetscAssertPointer(*submat, 6);
7249     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7250   }
7251   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7252   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7253   MatCheckPreallocated(mat, 1);
7254   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7255   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7256   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7257   for (i = 0; i < n; i++) {
7258     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7259     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7260     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7261 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7262     if (mat->boundtocpu && mat->bindingpropagates) {
7263       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7264       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7265     }
7266 #endif
7267   }
7268   PetscFunctionReturn(PETSC_SUCCESS);
7269 }
7270 
7271 /*@C
7272   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms).
7273 
7274   Collective
7275 
7276   Input Parameters:
7277 + mat   - the matrix
7278 . n     - the number of submatrixes to be extracted
7279 . irow  - index set of rows to extract
7280 . icol  - index set of columns to extract
7281 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7282 
7283   Output Parameter:
7284 . submat - the array of submatrices
7285 
7286   Level: advanced
7287 
7288   Note:
7289   This is used by `PCGASM`
7290 
7291 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7292 @*/
7293 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7294 {
7295   PetscInt  i;
7296   PetscBool eq;
7297 
7298   PetscFunctionBegin;
7299   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7300   PetscValidType(mat, 1);
7301   if (n) {
7302     PetscAssertPointer(irow, 3);
7303     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7304     PetscAssertPointer(icol, 4);
7305     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7306   }
7307   PetscAssertPointer(submat, 6);
7308   if (n && scall == MAT_REUSE_MATRIX) {
7309     PetscAssertPointer(*submat, 6);
7310     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7311   }
7312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7314   MatCheckPreallocated(mat, 1);
7315 
7316   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7317   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7318   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7319   for (i = 0; i < n; i++) {
7320     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7321     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7322   }
7323   PetscFunctionReturn(PETSC_SUCCESS);
7324 }
7325 
7326 /*@C
7327   MatDestroyMatrices - Destroys an array of matrices
7328 
7329   Collective
7330 
7331   Input Parameters:
7332 + n   - the number of local matrices
7333 - mat - the matrices (this is a pointer to the array of matrices)
7334 
7335   Level: advanced
7336 
7337   Notes:
7338   Frees not only the matrices, but also the array that contains the matrices
7339 
7340   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7341 
7342 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7343 @*/
7344 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7345 {
7346   PetscInt i;
7347 
7348   PetscFunctionBegin;
7349   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7350   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7351   PetscAssertPointer(mat, 2);
7352 
7353   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7354 
7355   /* memory is allocated even if n = 0 */
7356   PetscCall(PetscFree(*mat));
7357   PetscFunctionReturn(PETSC_SUCCESS);
7358 }
7359 
7360 /*@C
7361   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7362 
7363   Collective
7364 
7365   Input Parameters:
7366 + n   - the number of local matrices
7367 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`)
7368 
7369   Level: advanced
7370 
7371   Note:
7372   Frees not only the matrices, but also the array that contains the matrices
7373 
7374 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7375 @*/
7376 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7377 {
7378   Mat mat0;
7379 
7380   PetscFunctionBegin;
7381   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7382   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7383   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7384   PetscAssertPointer(mat, 2);
7385 
7386   mat0 = (*mat)[0];
7387   if (mat0 && mat0->ops->destroysubmatrices) {
7388     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7389   } else {
7390     PetscCall(MatDestroyMatrices(n, mat));
7391   }
7392   PetscFunctionReturn(PETSC_SUCCESS);
7393 }
7394 
7395 /*@
7396   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7397 
7398   Collective
7399 
7400   Input Parameter:
7401 . mat - the matrix
7402 
7403   Output Parameter:
7404 . matstruct - the sequential matrix with the nonzero structure of `mat`
7405 
7406   Level: developer
7407 
7408 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7409 @*/
7410 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7411 {
7412   PetscFunctionBegin;
7413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7414   PetscAssertPointer(matstruct, 2);
7415 
7416   PetscValidType(mat, 1);
7417   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7418   MatCheckPreallocated(mat, 1);
7419 
7420   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7421   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7422   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7423   PetscFunctionReturn(PETSC_SUCCESS);
7424 }
7425 
7426 /*@C
7427   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7428 
7429   Collective
7430 
7431   Input Parameter:
7432 . mat - the matrix
7433 
7434   Level: advanced
7435 
7436   Note:
7437   This is not needed, one can just call `MatDestroy()`
7438 
7439 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7440 @*/
7441 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7442 {
7443   PetscFunctionBegin;
7444   PetscAssertPointer(mat, 1);
7445   PetscCall(MatDestroy(mat));
7446   PetscFunctionReturn(PETSC_SUCCESS);
7447 }
7448 
7449 /*@
7450   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7451   replaces the index sets by larger ones that represent submatrices with
7452   additional overlap.
7453 
7454   Collective
7455 
7456   Input Parameters:
7457 + mat - the matrix
7458 . n   - the number of index sets
7459 . is  - the array of index sets (these index sets will changed during the call)
7460 - ov  - the additional overlap requested
7461 
7462   Options Database Key:
7463 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7464 
7465   Level: developer
7466 
7467   Note:
7468   The computed overlap preserves the matrix block sizes when the blocks are square.
7469   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7470   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7471 
7472 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7473 @*/
7474 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7475 {
7476   PetscInt i, bs, cbs;
7477 
7478   PetscFunctionBegin;
7479   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7480   PetscValidType(mat, 1);
7481   PetscValidLogicalCollectiveInt(mat, n, 2);
7482   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7483   if (n) {
7484     PetscAssertPointer(is, 3);
7485     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7486   }
7487   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7488   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7489   MatCheckPreallocated(mat, 1);
7490 
7491   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7492   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7493   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7494   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7495   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7496   if (bs == cbs) {
7497     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7498   }
7499   PetscFunctionReturn(PETSC_SUCCESS);
7500 }
7501 
7502 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7503 
7504 /*@
7505   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7506   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7507   additional overlap.
7508 
7509   Collective
7510 
7511   Input Parameters:
7512 + mat - the matrix
7513 . n   - the number of index sets
7514 . is  - the array of index sets (these index sets will changed during the call)
7515 - ov  - the additional overlap requested
7516 
7517   `   Options Database Key:
7518 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7519 
7520   Level: developer
7521 
7522 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7523 @*/
7524 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7525 {
7526   PetscInt i;
7527 
7528   PetscFunctionBegin;
7529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7530   PetscValidType(mat, 1);
7531   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7532   if (n) {
7533     PetscAssertPointer(is, 3);
7534     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7535   }
7536   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7537   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7538   MatCheckPreallocated(mat, 1);
7539   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7540   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7541   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7542   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7543   PetscFunctionReturn(PETSC_SUCCESS);
7544 }
7545 
7546 /*@
7547   MatGetBlockSize - Returns the matrix block size.
7548 
7549   Not Collective
7550 
7551   Input Parameter:
7552 . mat - the matrix
7553 
7554   Output Parameter:
7555 . bs - block size
7556 
7557   Level: intermediate
7558 
7559   Notes:
7560   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7561 
7562   If the block size has not been set yet this routine returns 1.
7563 
7564 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7565 @*/
7566 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7567 {
7568   PetscFunctionBegin;
7569   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7570   PetscAssertPointer(bs, 2);
7571   *bs = mat->rmap->bs;
7572   PetscFunctionReturn(PETSC_SUCCESS);
7573 }
7574 
7575 /*@
7576   MatGetBlockSizes - Returns the matrix block row and column sizes.
7577 
7578   Not Collective
7579 
7580   Input Parameter:
7581 . mat - the matrix
7582 
7583   Output Parameters:
7584 + rbs - row block size
7585 - cbs - column block size
7586 
7587   Level: intermediate
7588 
7589   Notes:
7590   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7591   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7592 
7593   If a block size has not been set yet this routine returns 1.
7594 
7595 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7596 @*/
7597 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7598 {
7599   PetscFunctionBegin;
7600   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7601   if (rbs) PetscAssertPointer(rbs, 2);
7602   if (cbs) PetscAssertPointer(cbs, 3);
7603   if (rbs) *rbs = mat->rmap->bs;
7604   if (cbs) *cbs = mat->cmap->bs;
7605   PetscFunctionReturn(PETSC_SUCCESS);
7606 }
7607 
7608 /*@
7609   MatSetBlockSize - Sets the matrix block size.
7610 
7611   Logically Collective
7612 
7613   Input Parameters:
7614 + mat - the matrix
7615 - bs  - block size
7616 
7617   Level: intermediate
7618 
7619   Notes:
7620   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7621   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7622 
7623   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7624   is compatible with the matrix local sizes.
7625 
7626 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7627 @*/
7628 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7629 {
7630   PetscFunctionBegin;
7631   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7632   PetscValidLogicalCollectiveInt(mat, bs, 2);
7633   PetscCall(MatSetBlockSizes(mat, bs, bs));
7634   PetscFunctionReturn(PETSC_SUCCESS);
7635 }
7636 
7637 typedef struct {
7638   PetscInt         n;
7639   IS              *is;
7640   Mat             *mat;
7641   PetscObjectState nonzerostate;
7642   Mat              C;
7643 } EnvelopeData;
7644 
7645 static PetscErrorCode EnvelopeDataDestroy(void **ptr)
7646 {
7647   EnvelopeData *edata = (EnvelopeData *)*ptr;
7648 
7649   PetscFunctionBegin;
7650   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7651   PetscCall(PetscFree(edata->is));
7652   PetscCall(PetscFree(edata));
7653   PetscFunctionReturn(PETSC_SUCCESS);
7654 }
7655 
7656 /*@
7657   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7658   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7659 
7660   Collective
7661 
7662   Input Parameter:
7663 . mat - the matrix
7664 
7665   Level: intermediate
7666 
7667   Notes:
7668   There can be zeros within the blocks
7669 
7670   The blocks can overlap between processes, including laying on more than two processes
7671 
7672 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7673 @*/
7674 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7675 {
7676   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7677   PetscInt          *diag, *odiag, sc;
7678   VecScatter         scatter;
7679   PetscScalar       *seqv;
7680   const PetscScalar *parv;
7681   const PetscInt    *ia, *ja;
7682   PetscBool          set, flag, done;
7683   Mat                AA = mat, A;
7684   MPI_Comm           comm;
7685   PetscMPIInt        rank, size, tag;
7686   MPI_Status         status;
7687   PetscContainer     container;
7688   EnvelopeData      *edata;
7689   Vec                seq, par;
7690   IS                 isglobal;
7691 
7692   PetscFunctionBegin;
7693   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7694   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7695   if (!set || !flag) {
7696     /* TODO: only needs nonzero structure of transpose */
7697     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7698     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7699   }
7700   PetscCall(MatAIJGetLocalMat(AA, &A));
7701   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7702   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7703 
7704   PetscCall(MatGetLocalSize(mat, &n, NULL));
7705   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7706   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7707   PetscCallMPI(MPI_Comm_size(comm, &size));
7708   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7709 
7710   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7711 
7712   if (rank > 0) {
7713     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7714     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7715   }
7716   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7717   for (i = 0; i < n; i++) {
7718     env = PetscMax(env, ja[ia[i + 1] - 1]);
7719     II  = rstart + i;
7720     if (env == II) {
7721       starts[lblocks]  = tbs;
7722       sizes[lblocks++] = 1 + II - tbs;
7723       tbs              = 1 + II;
7724     }
7725   }
7726   if (rank < size - 1) {
7727     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7728     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7729   }
7730 
7731   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7732   if (!set || !flag) PetscCall(MatDestroy(&AA));
7733   PetscCall(MatDestroy(&A));
7734 
7735   PetscCall(PetscNew(&edata));
7736   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7737   edata->n = lblocks;
7738   /* create IS needed for extracting blocks from the original matrix */
7739   PetscCall(PetscMalloc1(lblocks, &edata->is));
7740   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7741 
7742   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7743   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7744   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7745   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7746   PetscCall(MatSetType(edata->C, MATAIJ));
7747 
7748   /* Communicate the start and end of each row, from each block to the correct rank */
7749   /* TODO: Use PetscSF instead of VecScatter */
7750   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7751   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7752   PetscCall(VecGetArrayWrite(seq, &seqv));
7753   for (PetscInt i = 0; i < lblocks; i++) {
7754     for (PetscInt j = 0; j < sizes[i]; j++) {
7755       seqv[cnt]     = starts[i];
7756       seqv[cnt + 1] = starts[i] + sizes[i];
7757       cnt += 2;
7758     }
7759   }
7760   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7761   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7762   sc -= cnt;
7763   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7764   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7765   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7766   PetscCall(ISDestroy(&isglobal));
7767   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7768   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7769   PetscCall(VecScatterDestroy(&scatter));
7770   PetscCall(VecDestroy(&seq));
7771   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7772   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7773   PetscCall(VecGetArrayRead(par, &parv));
7774   cnt = 0;
7775   PetscCall(MatGetSize(mat, NULL, &n));
7776   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7777     PetscInt start, end, d = 0, od = 0;
7778 
7779     start = (PetscInt)PetscRealPart(parv[cnt]);
7780     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7781     cnt += 2;
7782 
7783     if (start < cstart) {
7784       od += cstart - start + n - cend;
7785       d += cend - cstart;
7786     } else if (start < cend) {
7787       od += n - cend;
7788       d += cend - start;
7789     } else od += n - start;
7790     if (end <= cstart) {
7791       od -= cstart - end + n - cend;
7792       d -= cend - cstart;
7793     } else if (end < cend) {
7794       od -= n - cend;
7795       d -= cend - end;
7796     } else od -= n - end;
7797 
7798     odiag[i] = od;
7799     diag[i]  = d;
7800   }
7801   PetscCall(VecRestoreArrayRead(par, &parv));
7802   PetscCall(VecDestroy(&par));
7803   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7804   PetscCall(PetscFree2(diag, odiag));
7805   PetscCall(PetscFree2(sizes, starts));
7806 
7807   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7808   PetscCall(PetscContainerSetPointer(container, edata));
7809   PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy));
7810   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7811   PetscCall(PetscObjectDereference((PetscObject)container));
7812   PetscFunctionReturn(PETSC_SUCCESS);
7813 }
7814 
7815 /*@
7816   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7817 
7818   Collective
7819 
7820   Input Parameters:
7821 + A     - the matrix
7822 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7823 
7824   Output Parameter:
7825 . C - matrix with inverted block diagonal of `A`
7826 
7827   Level: advanced
7828 
7829   Note:
7830   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7831 
7832 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7833 @*/
7834 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7835 {
7836   PetscContainer   container;
7837   EnvelopeData    *edata;
7838   PetscObjectState nonzerostate;
7839 
7840   PetscFunctionBegin;
7841   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7842   if (!container) {
7843     PetscCall(MatComputeVariableBlockEnvelope(A));
7844     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7845   }
7846   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7847   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7848   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7849   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7850 
7851   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7852   *C = edata->C;
7853 
7854   for (PetscInt i = 0; i < edata->n; i++) {
7855     Mat          D;
7856     PetscScalar *dvalues;
7857 
7858     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7859     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7860     PetscCall(MatSeqDenseInvert(D));
7861     PetscCall(MatDenseGetArray(D, &dvalues));
7862     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7863     PetscCall(MatDestroy(&D));
7864   }
7865   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7866   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7867   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7868   PetscFunctionReturn(PETSC_SUCCESS);
7869 }
7870 
7871 /*@
7872   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7873 
7874   Not Collective
7875 
7876   Input Parameters:
7877 + mat     - the matrix
7878 . nblocks - the number of blocks on this process, each block can only exist on a single process
7879 - bsizes  - the block sizes
7880 
7881   Level: intermediate
7882 
7883   Notes:
7884   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7885 
7886   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.
7887 
7888 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7889           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7890 @*/
7891 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7892 {
7893   PetscInt ncnt = 0, nlocal;
7894 
7895   PetscFunctionBegin;
7896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7897   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7898   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);
7899   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7900   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);
7901   PetscCall(PetscFree(mat->bsizes));
7902   mat->nblocks = nblocks;
7903   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7904   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7905   PetscFunctionReturn(PETSC_SUCCESS);
7906 }
7907 
7908 /*@C
7909   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7910 
7911   Not Collective; No Fortran Support
7912 
7913   Input Parameter:
7914 . mat - the matrix
7915 
7916   Output Parameters:
7917 + nblocks - the number of blocks on this process
7918 - bsizes  - the block sizes
7919 
7920   Level: intermediate
7921 
7922 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7923 @*/
7924 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7925 {
7926   PetscFunctionBegin;
7927   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7928   if (nblocks) *nblocks = mat->nblocks;
7929   if (bsizes) *bsizes = mat->bsizes;
7930   PetscFunctionReturn(PETSC_SUCCESS);
7931 }
7932 
7933 /*@
7934   MatSetBlockSizes - Sets the matrix block row and column sizes.
7935 
7936   Logically Collective
7937 
7938   Input Parameters:
7939 + mat - the matrix
7940 . rbs - row block size
7941 - cbs - column block size
7942 
7943   Level: intermediate
7944 
7945   Notes:
7946   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7947   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7948   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7949 
7950   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7951   are compatible with the matrix local sizes.
7952 
7953   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7954 
7955 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7956 @*/
7957 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7958 {
7959   PetscFunctionBegin;
7960   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7961   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7962   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7963   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7964   if (mat->rmap->refcnt) {
7965     ISLocalToGlobalMapping l2g  = NULL;
7966     PetscLayout            nmap = NULL;
7967 
7968     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7969     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7970     PetscCall(PetscLayoutDestroy(&mat->rmap));
7971     mat->rmap          = nmap;
7972     mat->rmap->mapping = l2g;
7973   }
7974   if (mat->cmap->refcnt) {
7975     ISLocalToGlobalMapping l2g  = NULL;
7976     PetscLayout            nmap = NULL;
7977 
7978     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7979     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7980     PetscCall(PetscLayoutDestroy(&mat->cmap));
7981     mat->cmap          = nmap;
7982     mat->cmap->mapping = l2g;
7983   }
7984   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7985   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7986   PetscFunctionReturn(PETSC_SUCCESS);
7987 }
7988 
7989 /*@
7990   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7991 
7992   Logically Collective
7993 
7994   Input Parameters:
7995 + mat     - the matrix
7996 . fromRow - matrix from which to copy row block size
7997 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7998 
7999   Level: developer
8000 
8001 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
8002 @*/
8003 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
8004 {
8005   PetscFunctionBegin;
8006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8007   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
8008   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
8009   PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
8010   PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
8011   PetscFunctionReturn(PETSC_SUCCESS);
8012 }
8013 
8014 /*@
8015   MatResidual - Default routine to calculate the residual r = b - Ax
8016 
8017   Collective
8018 
8019   Input Parameters:
8020 + mat - the matrix
8021 . b   - the right-hand-side
8022 - x   - the approximate solution
8023 
8024   Output Parameter:
8025 . r - location to store the residual
8026 
8027   Level: developer
8028 
8029 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8030 @*/
8031 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8032 {
8033   PetscFunctionBegin;
8034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8035   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8036   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8037   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8038   PetscValidType(mat, 1);
8039   MatCheckPreallocated(mat, 1);
8040   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8041   if (!mat->ops->residual) {
8042     PetscCall(MatMult(mat, x, r));
8043     PetscCall(VecAYPX(r, -1.0, b));
8044   } else {
8045     PetscUseTypeMethod(mat, residual, b, x, r);
8046   }
8047   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8048   PetscFunctionReturn(PETSC_SUCCESS);
8049 }
8050 
8051 /*@C
8052   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8053 
8054   Collective
8055 
8056   Input Parameters:
8057 + mat             - the matrix
8058 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8059 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8060 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8061                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8062                  always used.
8063 
8064   Output Parameters:
8065 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8066 . 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
8067 . ja   - the column indices, use `NULL` if not needed
8068 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8069            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8070 
8071   Level: developer
8072 
8073   Notes:
8074   You CANNOT change any of the ia[] or ja[] values.
8075 
8076   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8077 
8078   Fortran Notes:
8079   Use
8080 .vb
8081     PetscInt, pointer :: ia(:),ja(:)
8082     call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8083     ! Access the ith and jth entries via ia(i) and ja(j)
8084 .ve
8085 
8086 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8087 @*/
8088 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8089 {
8090   PetscFunctionBegin;
8091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8092   PetscValidType(mat, 1);
8093   if (n) PetscAssertPointer(n, 5);
8094   if (ia) PetscAssertPointer(ia, 6);
8095   if (ja) PetscAssertPointer(ja, 7);
8096   if (done) PetscAssertPointer(done, 8);
8097   MatCheckPreallocated(mat, 1);
8098   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8099   else {
8100     if (done) *done = PETSC_TRUE;
8101     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8102     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8103     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8104   }
8105   PetscFunctionReturn(PETSC_SUCCESS);
8106 }
8107 
8108 /*@C
8109   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8110 
8111   Collective
8112 
8113   Input Parameters:
8114 + mat             - the matrix
8115 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8116 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8117                 symmetrized
8118 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8119                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8120                  always used.
8121 . n               - number of columns in the (possibly compressed) matrix
8122 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8123 - ja              - the row indices
8124 
8125   Output Parameter:
8126 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8127 
8128   Level: developer
8129 
8130 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8131 @*/
8132 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8133 {
8134   PetscFunctionBegin;
8135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8136   PetscValidType(mat, 1);
8137   PetscAssertPointer(n, 5);
8138   if (ia) PetscAssertPointer(ia, 6);
8139   if (ja) PetscAssertPointer(ja, 7);
8140   PetscAssertPointer(done, 8);
8141   MatCheckPreallocated(mat, 1);
8142   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8143   else {
8144     *done = PETSC_TRUE;
8145     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8146   }
8147   PetscFunctionReturn(PETSC_SUCCESS);
8148 }
8149 
8150 /*@C
8151   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8152 
8153   Collective
8154 
8155   Input Parameters:
8156 + mat             - the matrix
8157 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8158 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8159 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8160                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8161                     always used.
8162 . n               - size of (possibly compressed) matrix
8163 . ia              - the row pointers
8164 - ja              - the column indices
8165 
8166   Output Parameter:
8167 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8168 
8169   Level: developer
8170 
8171   Note:
8172   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8173   us of the array after it has been restored. If you pass `NULL`, it will
8174   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8175 
8176 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8177 @*/
8178 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8179 {
8180   PetscFunctionBegin;
8181   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8182   PetscValidType(mat, 1);
8183   if (ia) PetscAssertPointer(ia, 6);
8184   if (ja) PetscAssertPointer(ja, 7);
8185   if (done) PetscAssertPointer(done, 8);
8186   MatCheckPreallocated(mat, 1);
8187 
8188   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8189   else {
8190     if (done) *done = PETSC_TRUE;
8191     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8192     if (n) *n = 0;
8193     if (ia) *ia = NULL;
8194     if (ja) *ja = NULL;
8195   }
8196   PetscFunctionReturn(PETSC_SUCCESS);
8197 }
8198 
8199 /*@C
8200   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8201 
8202   Collective
8203 
8204   Input Parameters:
8205 + mat             - the matrix
8206 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8207 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8208 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8209                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8210                     always used.
8211 
8212   Output Parameters:
8213 + n    - size of (possibly compressed) matrix
8214 . ia   - the column pointers
8215 . ja   - the row indices
8216 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8217 
8218   Level: developer
8219 
8220 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8221 @*/
8222 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8223 {
8224   PetscFunctionBegin;
8225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8226   PetscValidType(mat, 1);
8227   if (ia) PetscAssertPointer(ia, 6);
8228   if (ja) PetscAssertPointer(ja, 7);
8229   PetscAssertPointer(done, 8);
8230   MatCheckPreallocated(mat, 1);
8231 
8232   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8233   else {
8234     *done = PETSC_TRUE;
8235     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8236     if (n) *n = 0;
8237     if (ia) *ia = NULL;
8238     if (ja) *ja = NULL;
8239   }
8240   PetscFunctionReturn(PETSC_SUCCESS);
8241 }
8242 
8243 /*@
8244   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8245   `MatGetColumnIJ()`.
8246 
8247   Collective
8248 
8249   Input Parameters:
8250 + mat        - the matrix
8251 . ncolors    - maximum color value
8252 . n          - number of entries in colorarray
8253 - colorarray - array indicating color for each column
8254 
8255   Output Parameter:
8256 . iscoloring - coloring generated using colorarray information
8257 
8258   Level: developer
8259 
8260 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8261 @*/
8262 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8263 {
8264   PetscFunctionBegin;
8265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8266   PetscValidType(mat, 1);
8267   PetscAssertPointer(colorarray, 4);
8268   PetscAssertPointer(iscoloring, 5);
8269   MatCheckPreallocated(mat, 1);
8270 
8271   if (!mat->ops->coloringpatch) {
8272     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8273   } else {
8274     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8275   }
8276   PetscFunctionReturn(PETSC_SUCCESS);
8277 }
8278 
8279 /*@
8280   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8281 
8282   Logically Collective
8283 
8284   Input Parameter:
8285 . mat - the factored matrix to be reset
8286 
8287   Level: developer
8288 
8289   Notes:
8290   This routine should be used only with factored matrices formed by in-place
8291   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8292   format).  This option can save memory, for example, when solving nonlinear
8293   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8294   ILU(0) preconditioner.
8295 
8296   One can specify in-place ILU(0) factorization by calling
8297 .vb
8298      PCType(pc,PCILU);
8299      PCFactorSeUseInPlace(pc);
8300 .ve
8301   or by using the options -pc_type ilu -pc_factor_in_place
8302 
8303   In-place factorization ILU(0) can also be used as a local
8304   solver for the blocks within the block Jacobi or additive Schwarz
8305   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8306   for details on setting local solver options.
8307 
8308   Most users should employ the `KSP` interface for linear solvers
8309   instead of working directly with matrix algebra routines such as this.
8310   See, e.g., `KSPCreate()`.
8311 
8312 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8313 @*/
8314 PetscErrorCode MatSetUnfactored(Mat mat)
8315 {
8316   PetscFunctionBegin;
8317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8318   PetscValidType(mat, 1);
8319   MatCheckPreallocated(mat, 1);
8320   mat->factortype = MAT_FACTOR_NONE;
8321   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8322   PetscUseTypeMethod(mat, setunfactored);
8323   PetscFunctionReturn(PETSC_SUCCESS);
8324 }
8325 
8326 /*@
8327   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8328   as the original matrix.
8329 
8330   Collective
8331 
8332   Input Parameters:
8333 + mat   - the original matrix
8334 . isrow - parallel `IS` containing the rows this processor should obtain
8335 . 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.
8336 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8337 
8338   Output Parameter:
8339 . newmat - the new submatrix, of the same type as the original matrix
8340 
8341   Level: advanced
8342 
8343   Notes:
8344   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8345 
8346   Some matrix types place restrictions on the row and column indices, such
8347   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;
8348   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8349 
8350   The index sets may not have duplicate entries.
8351 
8352   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8353   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8354   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8355   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8356   you are finished using it.
8357 
8358   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8359   the input matrix.
8360 
8361   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8362 
8363   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8364   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8365 
8366   Example usage:
8367   Consider the following 8x8 matrix with 34 non-zero values, that is
8368   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8369   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8370   as follows
8371 .vb
8372             1  2  0  |  0  3  0  |  0  4
8373     Proc0   0  5  6  |  7  0  0  |  8  0
8374             9  0 10  | 11  0  0  | 12  0
8375     -------------------------------------
8376            13  0 14  | 15 16 17  |  0  0
8377     Proc1   0 18  0  | 19 20 21  |  0  0
8378             0  0  0  | 22 23  0  | 24  0
8379     -------------------------------------
8380     Proc2  25 26 27  |  0  0 28  | 29  0
8381            30  0  0  | 31 32 33  |  0 34
8382 .ve
8383 
8384   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8385 
8386 .vb
8387             2  0  |  0  3  0  |  0
8388     Proc0   5  6  |  7  0  0  |  8
8389     -------------------------------
8390     Proc1  18  0  | 19 20 21  |  0
8391     -------------------------------
8392     Proc2  26 27  |  0  0 28  | 29
8393             0  0  | 31 32 33  |  0
8394 .ve
8395 
8396 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8397 @*/
8398 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8399 {
8400   PetscMPIInt size;
8401   Mat        *local;
8402   IS          iscoltmp;
8403   PetscBool   flg;
8404 
8405   PetscFunctionBegin;
8406   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8407   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8408   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8409   PetscAssertPointer(newmat, 5);
8410   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8411   PetscValidType(mat, 1);
8412   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8413   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8414 
8415   MatCheckPreallocated(mat, 1);
8416   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8417 
8418   if (!iscol || isrow == iscol) {
8419     PetscBool   stride;
8420     PetscMPIInt grabentirematrix = 0, grab;
8421     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8422     if (stride) {
8423       PetscInt first, step, n, rstart, rend;
8424       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8425       if (step == 1) {
8426         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8427         if (rstart == first) {
8428           PetscCall(ISGetLocalSize(isrow, &n));
8429           if (n == rend - rstart) grabentirematrix = 1;
8430         }
8431       }
8432     }
8433     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8434     if (grab) {
8435       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8436       if (cll == MAT_INITIAL_MATRIX) {
8437         *newmat = mat;
8438         PetscCall(PetscObjectReference((PetscObject)mat));
8439       }
8440       PetscFunctionReturn(PETSC_SUCCESS);
8441     }
8442   }
8443 
8444   if (!iscol) {
8445     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8446   } else {
8447     iscoltmp = iscol;
8448   }
8449 
8450   /* if original matrix is on just one processor then use submatrix generated */
8451   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8452     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8453     goto setproperties;
8454   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8455     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8456     *newmat = *local;
8457     PetscCall(PetscFree(local));
8458     goto setproperties;
8459   } else if (!mat->ops->createsubmatrix) {
8460     /* Create a new matrix type that implements the operation using the full matrix */
8461     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8462     switch (cll) {
8463     case MAT_INITIAL_MATRIX:
8464       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8465       break;
8466     case MAT_REUSE_MATRIX:
8467       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8468       break;
8469     default:
8470       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8471     }
8472     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8473     goto setproperties;
8474   }
8475 
8476   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8477   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8478   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8479 
8480 setproperties:
8481   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8482     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8483     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8484   }
8485   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8486   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8487   PetscFunctionReturn(PETSC_SUCCESS);
8488 }
8489 
8490 /*@
8491   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8492 
8493   Not Collective
8494 
8495   Input Parameters:
8496 + A - the matrix we wish to propagate options from
8497 - B - the matrix we wish to propagate options to
8498 
8499   Level: beginner
8500 
8501   Note:
8502   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8503 
8504 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8505 @*/
8506 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8507 {
8508   PetscFunctionBegin;
8509   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8510   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8511   B->symmetry_eternal            = A->symmetry_eternal;
8512   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8513   B->symmetric                   = A->symmetric;
8514   B->structurally_symmetric      = A->structurally_symmetric;
8515   B->spd                         = A->spd;
8516   B->hermitian                   = A->hermitian;
8517   PetscFunctionReturn(PETSC_SUCCESS);
8518 }
8519 
8520 /*@
8521   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8522   used during the assembly process to store values that belong to
8523   other processors.
8524 
8525   Not Collective
8526 
8527   Input Parameters:
8528 + mat   - the matrix
8529 . size  - the initial size of the stash.
8530 - bsize - the initial size of the block-stash(if used).
8531 
8532   Options Database Keys:
8533 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8534 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8535 
8536   Level: intermediate
8537 
8538   Notes:
8539   The block-stash is used for values set with `MatSetValuesBlocked()` while
8540   the stash is used for values set with `MatSetValues()`
8541 
8542   Run with the option -info and look for output of the form
8543   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8544   to determine the appropriate value, MM, to use for size and
8545   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8546   to determine the value, BMM to use for bsize
8547 
8548 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8549 @*/
8550 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8551 {
8552   PetscFunctionBegin;
8553   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8554   PetscValidType(mat, 1);
8555   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8556   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8557   PetscFunctionReturn(PETSC_SUCCESS);
8558 }
8559 
8560 /*@
8561   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8562   the matrix
8563 
8564   Neighbor-wise Collective
8565 
8566   Input Parameters:
8567 + A - the matrix
8568 . x - the vector to be multiplied by the interpolation operator
8569 - y - the vector to be added to the result
8570 
8571   Output Parameter:
8572 . w - the resulting vector
8573 
8574   Level: intermediate
8575 
8576   Notes:
8577   `w` may be the same vector as `y`.
8578 
8579   This allows one to use either the restriction or interpolation (its transpose)
8580   matrix to do the interpolation
8581 
8582 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8583 @*/
8584 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8585 {
8586   PetscInt M, N, Ny;
8587 
8588   PetscFunctionBegin;
8589   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8590   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8591   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8592   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8593   PetscCall(MatGetSize(A, &M, &N));
8594   PetscCall(VecGetSize(y, &Ny));
8595   if (M == Ny) {
8596     PetscCall(MatMultAdd(A, x, y, w));
8597   } else {
8598     PetscCall(MatMultTransposeAdd(A, x, y, w));
8599   }
8600   PetscFunctionReturn(PETSC_SUCCESS);
8601 }
8602 
8603 /*@
8604   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8605   the matrix
8606 
8607   Neighbor-wise Collective
8608 
8609   Input Parameters:
8610 + A - the matrix
8611 - x - the vector to be interpolated
8612 
8613   Output Parameter:
8614 . y - the resulting vector
8615 
8616   Level: intermediate
8617 
8618   Note:
8619   This allows one to use either the restriction or interpolation (its transpose)
8620   matrix to do the interpolation
8621 
8622 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8623 @*/
8624 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8625 {
8626   PetscInt M, N, Ny;
8627 
8628   PetscFunctionBegin;
8629   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8630   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8631   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8632   PetscCall(MatGetSize(A, &M, &N));
8633   PetscCall(VecGetSize(y, &Ny));
8634   if (M == Ny) {
8635     PetscCall(MatMult(A, x, y));
8636   } else {
8637     PetscCall(MatMultTranspose(A, x, y));
8638   }
8639   PetscFunctionReturn(PETSC_SUCCESS);
8640 }
8641 
8642 /*@
8643   MatRestrict - $y = A*x$ or $A^T*x$
8644 
8645   Neighbor-wise Collective
8646 
8647   Input Parameters:
8648 + A - the matrix
8649 - x - the vector to be restricted
8650 
8651   Output Parameter:
8652 . y - the resulting vector
8653 
8654   Level: intermediate
8655 
8656   Note:
8657   This allows one to use either the restriction or interpolation (its transpose)
8658   matrix to do the restriction
8659 
8660 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8661 @*/
8662 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8663 {
8664   PetscInt M, N, Nx;
8665 
8666   PetscFunctionBegin;
8667   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8668   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8669   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8670   PetscCall(MatGetSize(A, &M, &N));
8671   PetscCall(VecGetSize(x, &Nx));
8672   if (M == Nx) {
8673     PetscCall(MatMultTranspose(A, x, y));
8674   } else {
8675     PetscCall(MatMult(A, x, y));
8676   }
8677   PetscFunctionReturn(PETSC_SUCCESS);
8678 }
8679 
8680 /*@
8681   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8682 
8683   Neighbor-wise Collective
8684 
8685   Input Parameters:
8686 + A - the matrix
8687 . x - the input dense matrix to be multiplied
8688 - w - the input dense matrix to be added to the result
8689 
8690   Output Parameter:
8691 . y - the output dense matrix
8692 
8693   Level: intermediate
8694 
8695   Note:
8696   This allows one to use either the restriction or interpolation (its transpose)
8697   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8698   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8699 
8700 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8701 @*/
8702 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8703 {
8704   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8705   PetscBool trans = PETSC_TRUE;
8706   MatReuse  reuse = MAT_INITIAL_MATRIX;
8707 
8708   PetscFunctionBegin;
8709   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8710   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8711   PetscValidType(x, 2);
8712   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8713   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8714   PetscCall(MatGetSize(A, &M, &N));
8715   PetscCall(MatGetSize(x, &Mx, &Nx));
8716   if (N == Mx) trans = PETSC_FALSE;
8717   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);
8718   Mo = trans ? N : M;
8719   if (*y) {
8720     PetscCall(MatGetSize(*y, &My, &Ny));
8721     if (Mo == My && Nx == Ny) {
8722       reuse = MAT_REUSE_MATRIX;
8723     } else {
8724       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);
8725       PetscCall(MatDestroy(y));
8726     }
8727   }
8728 
8729   if (w && *y == w) { /* this is to minimize changes in PCMG */
8730     PetscBool flg;
8731 
8732     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8733     if (w) {
8734       PetscInt My, Ny, Mw, Nw;
8735 
8736       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8737       PetscCall(MatGetSize(*y, &My, &Ny));
8738       PetscCall(MatGetSize(w, &Mw, &Nw));
8739       if (!flg || My != Mw || Ny != Nw) w = NULL;
8740     }
8741     if (!w) {
8742       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8743       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8744       PetscCall(PetscObjectDereference((PetscObject)w));
8745     } else {
8746       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8747     }
8748   }
8749   if (!trans) {
8750     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8751   } else {
8752     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8753   }
8754   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8755   PetscFunctionReturn(PETSC_SUCCESS);
8756 }
8757 
8758 /*@
8759   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8760 
8761   Neighbor-wise Collective
8762 
8763   Input Parameters:
8764 + A - the matrix
8765 - x - the input dense matrix
8766 
8767   Output Parameter:
8768 . y - the output dense matrix
8769 
8770   Level: intermediate
8771 
8772   Note:
8773   This allows one to use either the restriction or interpolation (its transpose)
8774   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8775   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8776 
8777 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8778 @*/
8779 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8780 {
8781   PetscFunctionBegin;
8782   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8783   PetscFunctionReturn(PETSC_SUCCESS);
8784 }
8785 
8786 /*@
8787   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8788 
8789   Neighbor-wise Collective
8790 
8791   Input Parameters:
8792 + A - the matrix
8793 - x - the input dense matrix
8794 
8795   Output Parameter:
8796 . y - the output dense matrix
8797 
8798   Level: intermediate
8799 
8800   Note:
8801   This allows one to use either the restriction or interpolation (its transpose)
8802   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8803   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8804 
8805 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8806 @*/
8807 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8808 {
8809   PetscFunctionBegin;
8810   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8811   PetscFunctionReturn(PETSC_SUCCESS);
8812 }
8813 
8814 /*@
8815   MatGetNullSpace - retrieves the null space of a matrix.
8816 
8817   Logically Collective
8818 
8819   Input Parameters:
8820 + mat    - the matrix
8821 - nullsp - the null space object
8822 
8823   Level: developer
8824 
8825 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8826 @*/
8827 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8828 {
8829   PetscFunctionBegin;
8830   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8831   PetscAssertPointer(nullsp, 2);
8832   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8833   PetscFunctionReturn(PETSC_SUCCESS);
8834 }
8835 
8836 /*@C
8837   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8838 
8839   Logically Collective
8840 
8841   Input Parameters:
8842 + n   - the number of matrices
8843 - mat - the array of matrices
8844 
8845   Output Parameters:
8846 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
8847 
8848   Level: developer
8849 
8850   Note:
8851   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8852 
8853 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8854           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8855 @*/
8856 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8857 {
8858   PetscFunctionBegin;
8859   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8860   PetscAssertPointer(mat, 2);
8861   PetscAssertPointer(nullsp, 3);
8862 
8863   PetscCall(PetscCalloc1(3 * n, nullsp));
8864   for (PetscInt i = 0; i < n; i++) {
8865     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8866     (*nullsp)[i] = mat[i]->nullsp;
8867     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8868     (*nullsp)[n + i] = mat[i]->nearnullsp;
8869     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8870     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8871     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8872   }
8873   PetscFunctionReturn(PETSC_SUCCESS);
8874 }
8875 
8876 /*@C
8877   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8878 
8879   Logically Collective
8880 
8881   Input Parameters:
8882 + n      - the number of matrices
8883 . mat    - the array of matrices
8884 - nullsp - an array of null spaces
8885 
8886   Level: developer
8887 
8888   Note:
8889   Call `MatGetNullSpaces()` to create `nullsp`
8890 
8891 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8892           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
8893 @*/
8894 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8895 {
8896   PetscFunctionBegin;
8897   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8898   PetscAssertPointer(mat, 2);
8899   PetscAssertPointer(nullsp, 3);
8900   PetscAssertPointer(*nullsp, 3);
8901 
8902   for (PetscInt i = 0; i < n; i++) {
8903     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8904     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
8905     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
8906     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
8907     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
8908     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
8909     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
8910   }
8911   PetscCall(PetscFree(*nullsp));
8912   PetscFunctionReturn(PETSC_SUCCESS);
8913 }
8914 
8915 /*@
8916   MatSetNullSpace - attaches a null space to a matrix.
8917 
8918   Logically Collective
8919 
8920   Input Parameters:
8921 + mat    - the matrix
8922 - nullsp - the null space object
8923 
8924   Level: advanced
8925 
8926   Notes:
8927   This null space is used by the `KSP` linear solvers to solve singular systems.
8928 
8929   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`
8930 
8931   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
8932   to zero but the linear system will still be solved in a least squares sense.
8933 
8934   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8935   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)$.
8936   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
8937   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
8938   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$).
8939   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8940 
8941   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8942   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8943   routine also automatically calls `MatSetTransposeNullSpace()`.
8944 
8945   The user should call `MatNullSpaceDestroy()`.
8946 
8947 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8948           `KSPSetPCSide()`
8949 @*/
8950 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8951 {
8952   PetscFunctionBegin;
8953   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8954   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8955   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8956   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8957   mat->nullsp = nullsp;
8958   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8959   PetscFunctionReturn(PETSC_SUCCESS);
8960 }
8961 
8962 /*@
8963   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8964 
8965   Logically Collective
8966 
8967   Input Parameters:
8968 + mat    - the matrix
8969 - nullsp - the null space object
8970 
8971   Level: developer
8972 
8973 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8974 @*/
8975 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8976 {
8977   PetscFunctionBegin;
8978   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8979   PetscValidType(mat, 1);
8980   PetscAssertPointer(nullsp, 2);
8981   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8982   PetscFunctionReturn(PETSC_SUCCESS);
8983 }
8984 
8985 /*@
8986   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8987 
8988   Logically Collective
8989 
8990   Input Parameters:
8991 + mat    - the matrix
8992 - nullsp - the null space object
8993 
8994   Level: advanced
8995 
8996   Notes:
8997   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8998 
8999   See `MatSetNullSpace()`
9000 
9001 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9002 @*/
9003 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9004 {
9005   PetscFunctionBegin;
9006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9007   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9008   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9009   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9010   mat->transnullsp = nullsp;
9011   PetscFunctionReturn(PETSC_SUCCESS);
9012 }
9013 
9014 /*@
9015   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9016   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9017 
9018   Logically Collective
9019 
9020   Input Parameters:
9021 + mat    - the matrix
9022 - nullsp - the null space object
9023 
9024   Level: advanced
9025 
9026   Notes:
9027   Overwrites any previous near null space that may have been attached
9028 
9029   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9030 
9031 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9032 @*/
9033 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9034 {
9035   PetscFunctionBegin;
9036   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9037   PetscValidType(mat, 1);
9038   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9039   MatCheckPreallocated(mat, 1);
9040   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9041   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9042   mat->nearnullsp = nullsp;
9043   PetscFunctionReturn(PETSC_SUCCESS);
9044 }
9045 
9046 /*@
9047   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9048 
9049   Not Collective
9050 
9051   Input Parameter:
9052 . mat - the matrix
9053 
9054   Output Parameter:
9055 . nullsp - the null space object, `NULL` if not set
9056 
9057   Level: advanced
9058 
9059 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9060 @*/
9061 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9062 {
9063   PetscFunctionBegin;
9064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9065   PetscValidType(mat, 1);
9066   PetscAssertPointer(nullsp, 2);
9067   MatCheckPreallocated(mat, 1);
9068   *nullsp = mat->nearnullsp;
9069   PetscFunctionReturn(PETSC_SUCCESS);
9070 }
9071 
9072 /*@
9073   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9074 
9075   Collective
9076 
9077   Input Parameters:
9078 + mat  - the matrix
9079 . row  - row/column permutation
9080 - info - information on desired factorization process
9081 
9082   Level: developer
9083 
9084   Notes:
9085   Probably really in-place only when level of fill is zero, otherwise allocates
9086   new space to store factored matrix and deletes previous memory.
9087 
9088   Most users should employ the `KSP` interface for linear solvers
9089   instead of working directly with matrix algebra routines such as this.
9090   See, e.g., `KSPCreate()`.
9091 
9092   Developer Note:
9093   The Fortran interface is not autogenerated as the
9094   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9095 
9096 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9097 @*/
9098 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9099 {
9100   PetscFunctionBegin;
9101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9102   PetscValidType(mat, 1);
9103   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9104   PetscAssertPointer(info, 3);
9105   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9106   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9107   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9108   MatCheckPreallocated(mat, 1);
9109   PetscUseTypeMethod(mat, iccfactor, row, info);
9110   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9111   PetscFunctionReturn(PETSC_SUCCESS);
9112 }
9113 
9114 /*@
9115   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9116   ghosted ones.
9117 
9118   Not Collective
9119 
9120   Input Parameters:
9121 + mat  - the matrix
9122 - diag - the diagonal values, including ghost ones
9123 
9124   Level: developer
9125 
9126   Notes:
9127   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9128 
9129   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9130 
9131 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9132 @*/
9133 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9134 {
9135   PetscMPIInt size;
9136 
9137   PetscFunctionBegin;
9138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9139   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9140   PetscValidType(mat, 1);
9141 
9142   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9143   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9144   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9145   if (size == 1) {
9146     PetscInt n, m;
9147     PetscCall(VecGetSize(diag, &n));
9148     PetscCall(MatGetSize(mat, NULL, &m));
9149     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9150     PetscCall(MatDiagonalScale(mat, NULL, diag));
9151   } else {
9152     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9153   }
9154   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9155   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9156   PetscFunctionReturn(PETSC_SUCCESS);
9157 }
9158 
9159 /*@
9160   MatGetInertia - Gets the inertia from a factored matrix
9161 
9162   Collective
9163 
9164   Input Parameter:
9165 . mat - the matrix
9166 
9167   Output Parameters:
9168 + nneg  - number of negative eigenvalues
9169 . nzero - number of zero eigenvalues
9170 - npos  - number of positive eigenvalues
9171 
9172   Level: advanced
9173 
9174   Note:
9175   Matrix must have been factored by `MatCholeskyFactor()`
9176 
9177 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9178 @*/
9179 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9180 {
9181   PetscFunctionBegin;
9182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9183   PetscValidType(mat, 1);
9184   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9185   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9186   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9187   PetscFunctionReturn(PETSC_SUCCESS);
9188 }
9189 
9190 /*@C
9191   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9192 
9193   Neighbor-wise Collective
9194 
9195   Input Parameters:
9196 + mat - the factored matrix obtained with `MatGetFactor()`
9197 - b   - the right-hand-side vectors
9198 
9199   Output Parameter:
9200 . x - the result vectors
9201 
9202   Level: developer
9203 
9204   Note:
9205   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9206   call `MatSolves`(A,x,x).
9207 
9208 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9209 @*/
9210 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9211 {
9212   PetscFunctionBegin;
9213   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9214   PetscValidType(mat, 1);
9215   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9216   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9217   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9218 
9219   MatCheckPreallocated(mat, 1);
9220   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9221   PetscUseTypeMethod(mat, solves, b, x);
9222   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9223   PetscFunctionReturn(PETSC_SUCCESS);
9224 }
9225 
9226 /*@
9227   MatIsSymmetric - Test whether a matrix is symmetric
9228 
9229   Collective
9230 
9231   Input Parameters:
9232 + A   - the matrix to test
9233 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9234 
9235   Output Parameter:
9236 . flg - the result
9237 
9238   Level: intermediate
9239 
9240   Notes:
9241   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9242 
9243   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9244 
9245   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9246   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9247 
9248 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9249           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9250 @*/
9251 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9252 {
9253   PetscFunctionBegin;
9254   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9255   PetscAssertPointer(flg, 3);
9256   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9257   else {
9258     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9259     else PetscCall(MatIsTranspose(A, A, tol, flg));
9260     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9261   }
9262   PetscFunctionReturn(PETSC_SUCCESS);
9263 }
9264 
9265 /*@
9266   MatIsHermitian - Test whether a matrix is Hermitian
9267 
9268   Collective
9269 
9270   Input Parameters:
9271 + A   - the matrix to test
9272 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9273 
9274   Output Parameter:
9275 . flg - the result
9276 
9277   Level: intermediate
9278 
9279   Notes:
9280   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9281 
9282   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9283 
9284   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9285   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9286 
9287 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9288           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9289 @*/
9290 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9291 {
9292   PetscFunctionBegin;
9293   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9294   PetscAssertPointer(flg, 3);
9295   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9296   else {
9297     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9298     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9299     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9300   }
9301   PetscFunctionReturn(PETSC_SUCCESS);
9302 }
9303 
9304 /*@
9305   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9306 
9307   Not Collective
9308 
9309   Input Parameter:
9310 . A - the matrix to check
9311 
9312   Output Parameters:
9313 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9314 - flg - the result (only valid if set is `PETSC_TRUE`)
9315 
9316   Level: advanced
9317 
9318   Notes:
9319   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9320   if you want it explicitly checked
9321 
9322   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9323   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9324 
9325 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9326 @*/
9327 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9328 {
9329   PetscFunctionBegin;
9330   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9331   PetscAssertPointer(set, 2);
9332   PetscAssertPointer(flg, 3);
9333   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9334     *set = PETSC_TRUE;
9335     *flg = PetscBool3ToBool(A->symmetric);
9336   } else {
9337     *set = PETSC_FALSE;
9338   }
9339   PetscFunctionReturn(PETSC_SUCCESS);
9340 }
9341 
9342 /*@
9343   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9344 
9345   Not Collective
9346 
9347   Input Parameter:
9348 . A - the matrix to check
9349 
9350   Output Parameters:
9351 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9352 - flg - the result (only valid if set is `PETSC_TRUE`)
9353 
9354   Level: advanced
9355 
9356   Notes:
9357   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9358 
9359   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9360   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9361 
9362 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9363 @*/
9364 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9365 {
9366   PetscFunctionBegin;
9367   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9368   PetscAssertPointer(set, 2);
9369   PetscAssertPointer(flg, 3);
9370   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9371     *set = PETSC_TRUE;
9372     *flg = PetscBool3ToBool(A->spd);
9373   } else {
9374     *set = PETSC_FALSE;
9375   }
9376   PetscFunctionReturn(PETSC_SUCCESS);
9377 }
9378 
9379 /*@
9380   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9381 
9382   Not Collective
9383 
9384   Input Parameter:
9385 . A - the matrix to check
9386 
9387   Output Parameters:
9388 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9389 - flg - the result (only valid if set is `PETSC_TRUE`)
9390 
9391   Level: advanced
9392 
9393   Notes:
9394   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9395   if you want it explicitly checked
9396 
9397   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9398   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9399 
9400 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9401 @*/
9402 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9403 {
9404   PetscFunctionBegin;
9405   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9406   PetscAssertPointer(set, 2);
9407   PetscAssertPointer(flg, 3);
9408   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9409     *set = PETSC_TRUE;
9410     *flg = PetscBool3ToBool(A->hermitian);
9411   } else {
9412     *set = PETSC_FALSE;
9413   }
9414   PetscFunctionReturn(PETSC_SUCCESS);
9415 }
9416 
9417 /*@
9418   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9419 
9420   Collective
9421 
9422   Input Parameter:
9423 . A - the matrix to test
9424 
9425   Output Parameter:
9426 . flg - the result
9427 
9428   Level: intermediate
9429 
9430   Notes:
9431   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9432 
9433   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
9434   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9435 
9436 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9437 @*/
9438 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9439 {
9440   PetscFunctionBegin;
9441   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9442   PetscAssertPointer(flg, 2);
9443   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9444     *flg = PetscBool3ToBool(A->structurally_symmetric);
9445   } else {
9446     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9447     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9448   }
9449   PetscFunctionReturn(PETSC_SUCCESS);
9450 }
9451 
9452 /*@
9453   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9454 
9455   Not Collective
9456 
9457   Input Parameter:
9458 . A - the matrix to check
9459 
9460   Output Parameters:
9461 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9462 - flg - the result (only valid if set is PETSC_TRUE)
9463 
9464   Level: advanced
9465 
9466   Notes:
9467   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
9468   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9469 
9470   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9471 
9472 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9473 @*/
9474 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9475 {
9476   PetscFunctionBegin;
9477   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9478   PetscAssertPointer(set, 2);
9479   PetscAssertPointer(flg, 3);
9480   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9481     *set = PETSC_TRUE;
9482     *flg = PetscBool3ToBool(A->structurally_symmetric);
9483   } else {
9484     *set = PETSC_FALSE;
9485   }
9486   PetscFunctionReturn(PETSC_SUCCESS);
9487 }
9488 
9489 /*@
9490   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9491   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9492 
9493   Not Collective
9494 
9495   Input Parameter:
9496 . mat - the matrix
9497 
9498   Output Parameters:
9499 + nstash    - the size of the stash
9500 . reallocs  - the number of additional mallocs incurred.
9501 . bnstash   - the size of the block stash
9502 - breallocs - the number of additional mallocs incurred.in the block stash
9503 
9504   Level: advanced
9505 
9506 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9507 @*/
9508 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9509 {
9510   PetscFunctionBegin;
9511   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9512   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9513   PetscFunctionReturn(PETSC_SUCCESS);
9514 }
9515 
9516 /*@
9517   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9518   parallel layout, `PetscLayout` for rows and columns
9519 
9520   Collective
9521 
9522   Input Parameter:
9523 . mat - the matrix
9524 
9525   Output Parameters:
9526 + right - (optional) vector that the matrix can be multiplied against
9527 - left  - (optional) vector that the matrix vector product can be stored in
9528 
9529   Level: advanced
9530 
9531   Notes:
9532   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()`.
9533 
9534   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9535 
9536 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9537 @*/
9538 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9539 {
9540   PetscFunctionBegin;
9541   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9542   PetscValidType(mat, 1);
9543   if (mat->ops->getvecs) {
9544     PetscUseTypeMethod(mat, getvecs, right, left);
9545   } else {
9546     if (right) {
9547       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9548       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9549       PetscCall(VecSetType(*right, mat->defaultvectype));
9550 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9551       if (mat->boundtocpu && mat->bindingpropagates) {
9552         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9553         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9554       }
9555 #endif
9556     }
9557     if (left) {
9558       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9559       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9560       PetscCall(VecSetType(*left, mat->defaultvectype));
9561 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9562       if (mat->boundtocpu && mat->bindingpropagates) {
9563         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9564         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9565       }
9566 #endif
9567     }
9568   }
9569   PetscFunctionReturn(PETSC_SUCCESS);
9570 }
9571 
9572 /*@
9573   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9574   with default values.
9575 
9576   Not Collective
9577 
9578   Input Parameter:
9579 . info - the `MatFactorInfo` data structure
9580 
9581   Level: developer
9582 
9583   Notes:
9584   The solvers are generally used through the `KSP` and `PC` objects, for example
9585   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9586 
9587   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9588 
9589 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9590 @*/
9591 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9592 {
9593   PetscFunctionBegin;
9594   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9595   PetscFunctionReturn(PETSC_SUCCESS);
9596 }
9597 
9598 /*@
9599   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9600 
9601   Collective
9602 
9603   Input Parameters:
9604 + mat - the factored matrix
9605 - is  - the index set defining the Schur indices (0-based)
9606 
9607   Level: advanced
9608 
9609   Notes:
9610   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9611 
9612   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9613 
9614   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9615 
9616 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9617           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9618 @*/
9619 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9620 {
9621   PetscErrorCode (*f)(Mat, IS);
9622 
9623   PetscFunctionBegin;
9624   PetscValidType(mat, 1);
9625   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9626   PetscValidType(is, 2);
9627   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9628   PetscCheckSameComm(mat, 1, is, 2);
9629   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9630   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9631   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9632   PetscCall(MatDestroy(&mat->schur));
9633   PetscCall((*f)(mat, is));
9634   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9635   PetscFunctionReturn(PETSC_SUCCESS);
9636 }
9637 
9638 /*@
9639   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9640 
9641   Logically Collective
9642 
9643   Input Parameters:
9644 + F      - the factored matrix obtained by calling `MatGetFactor()`
9645 . S      - location where to return the Schur complement, can be `NULL`
9646 - status - the status of the Schur complement matrix, can be `NULL`
9647 
9648   Level: advanced
9649 
9650   Notes:
9651   You must call `MatFactorSetSchurIS()` before calling this routine.
9652 
9653   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9654 
9655   The routine provides a copy of the Schur matrix stored within the solver data structures.
9656   The caller must destroy the object when it is no longer needed.
9657   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9658 
9659   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)
9660 
9661   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9662 
9663   Developer Note:
9664   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9665   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9666 
9667 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9668 @*/
9669 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9670 {
9671   PetscFunctionBegin;
9672   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9673   if (S) PetscAssertPointer(S, 2);
9674   if (status) PetscAssertPointer(status, 3);
9675   if (S) {
9676     PetscErrorCode (*f)(Mat, Mat *);
9677 
9678     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9679     if (f) {
9680       PetscCall((*f)(F, S));
9681     } else {
9682       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9683     }
9684   }
9685   if (status) *status = F->schur_status;
9686   PetscFunctionReturn(PETSC_SUCCESS);
9687 }
9688 
9689 /*@
9690   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9691 
9692   Logically Collective
9693 
9694   Input Parameters:
9695 + F      - the factored matrix obtained by calling `MatGetFactor()`
9696 . S      - location where to return the Schur complement, can be `NULL`
9697 - status - the status of the Schur complement matrix, can be `NULL`
9698 
9699   Level: advanced
9700 
9701   Notes:
9702   You must call `MatFactorSetSchurIS()` before calling this routine.
9703 
9704   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9705 
9706   The routine returns a the Schur Complement stored within the data structures of the solver.
9707 
9708   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9709 
9710   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9711 
9712   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9713 
9714   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9715 
9716 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9717 @*/
9718 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9719 {
9720   PetscFunctionBegin;
9721   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9722   if (S) {
9723     PetscAssertPointer(S, 2);
9724     *S = F->schur;
9725   }
9726   if (status) {
9727     PetscAssertPointer(status, 3);
9728     *status = F->schur_status;
9729   }
9730   PetscFunctionReturn(PETSC_SUCCESS);
9731 }
9732 
9733 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9734 {
9735   Mat S = F->schur;
9736 
9737   PetscFunctionBegin;
9738   switch (F->schur_status) {
9739   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9740   case MAT_FACTOR_SCHUR_INVERTED:
9741     if (S) {
9742       S->ops->solve             = NULL;
9743       S->ops->matsolve          = NULL;
9744       S->ops->solvetranspose    = NULL;
9745       S->ops->matsolvetranspose = NULL;
9746       S->ops->solveadd          = NULL;
9747       S->ops->solvetransposeadd = NULL;
9748       S->factortype             = MAT_FACTOR_NONE;
9749       PetscCall(PetscFree(S->solvertype));
9750     }
9751   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9752     break;
9753   default:
9754     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9755   }
9756   PetscFunctionReturn(PETSC_SUCCESS);
9757 }
9758 
9759 /*@
9760   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9761 
9762   Logically Collective
9763 
9764   Input Parameters:
9765 + F      - the factored matrix obtained by calling `MatGetFactor()`
9766 . S      - location where the Schur complement is stored
9767 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9768 
9769   Level: advanced
9770 
9771 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9772 @*/
9773 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9774 {
9775   PetscFunctionBegin;
9776   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9777   if (S) {
9778     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9779     *S = NULL;
9780   }
9781   F->schur_status = status;
9782   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9783   PetscFunctionReturn(PETSC_SUCCESS);
9784 }
9785 
9786 /*@
9787   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9788 
9789   Logically Collective
9790 
9791   Input Parameters:
9792 + F   - the factored matrix obtained by calling `MatGetFactor()`
9793 . rhs - location where the right-hand side of the Schur complement system is stored
9794 - sol - location where the solution of the Schur complement system has to be returned
9795 
9796   Level: advanced
9797 
9798   Notes:
9799   The sizes of the vectors should match the size of the Schur complement
9800 
9801   Must be called after `MatFactorSetSchurIS()`
9802 
9803 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9804 @*/
9805 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9806 {
9807   PetscFunctionBegin;
9808   PetscValidType(F, 1);
9809   PetscValidType(rhs, 2);
9810   PetscValidType(sol, 3);
9811   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9812   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9813   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9814   PetscCheckSameComm(F, 1, rhs, 2);
9815   PetscCheckSameComm(F, 1, sol, 3);
9816   PetscCall(MatFactorFactorizeSchurComplement(F));
9817   switch (F->schur_status) {
9818   case MAT_FACTOR_SCHUR_FACTORED:
9819     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9820     break;
9821   case MAT_FACTOR_SCHUR_INVERTED:
9822     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9823     break;
9824   default:
9825     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9826   }
9827   PetscFunctionReturn(PETSC_SUCCESS);
9828 }
9829 
9830 /*@
9831   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9832 
9833   Logically Collective
9834 
9835   Input Parameters:
9836 + F   - the factored matrix obtained by calling `MatGetFactor()`
9837 . rhs - location where the right-hand side of the Schur complement system is stored
9838 - sol - location where the solution of the Schur complement system has to be returned
9839 
9840   Level: advanced
9841 
9842   Notes:
9843   The sizes of the vectors should match the size of the Schur complement
9844 
9845   Must be called after `MatFactorSetSchurIS()`
9846 
9847 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9848 @*/
9849 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9850 {
9851   PetscFunctionBegin;
9852   PetscValidType(F, 1);
9853   PetscValidType(rhs, 2);
9854   PetscValidType(sol, 3);
9855   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9856   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9857   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9858   PetscCheckSameComm(F, 1, rhs, 2);
9859   PetscCheckSameComm(F, 1, sol, 3);
9860   PetscCall(MatFactorFactorizeSchurComplement(F));
9861   switch (F->schur_status) {
9862   case MAT_FACTOR_SCHUR_FACTORED:
9863     PetscCall(MatSolve(F->schur, rhs, sol));
9864     break;
9865   case MAT_FACTOR_SCHUR_INVERTED:
9866     PetscCall(MatMult(F->schur, rhs, sol));
9867     break;
9868   default:
9869     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9870   }
9871   PetscFunctionReturn(PETSC_SUCCESS);
9872 }
9873 
9874 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9875 #if PetscDefined(HAVE_CUDA)
9876 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9877 #endif
9878 
9879 /* Schur status updated in the interface */
9880 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9881 {
9882   Mat S = F->schur;
9883 
9884   PetscFunctionBegin;
9885   if (S) {
9886     PetscMPIInt size;
9887     PetscBool   isdense, isdensecuda;
9888 
9889     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9890     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9891     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9892     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9893     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9894     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9895     if (isdense) {
9896       PetscCall(MatSeqDenseInvertFactors_Private(S));
9897     } else if (isdensecuda) {
9898 #if defined(PETSC_HAVE_CUDA)
9899       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9900 #endif
9901     }
9902     // HIP??????????????
9903     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9904   }
9905   PetscFunctionReturn(PETSC_SUCCESS);
9906 }
9907 
9908 /*@
9909   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9910 
9911   Logically Collective
9912 
9913   Input Parameter:
9914 . F - the factored matrix obtained by calling `MatGetFactor()`
9915 
9916   Level: advanced
9917 
9918   Notes:
9919   Must be called after `MatFactorSetSchurIS()`.
9920 
9921   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9922 
9923 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9924 @*/
9925 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9926 {
9927   PetscFunctionBegin;
9928   PetscValidType(F, 1);
9929   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9930   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9931   PetscCall(MatFactorFactorizeSchurComplement(F));
9932   PetscCall(MatFactorInvertSchurComplement_Private(F));
9933   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9934   PetscFunctionReturn(PETSC_SUCCESS);
9935 }
9936 
9937 /*@
9938   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9939 
9940   Logically Collective
9941 
9942   Input Parameter:
9943 . F - the factored matrix obtained by calling `MatGetFactor()`
9944 
9945   Level: advanced
9946 
9947   Note:
9948   Must be called after `MatFactorSetSchurIS()`
9949 
9950 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9951 @*/
9952 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9953 {
9954   MatFactorInfo info;
9955 
9956   PetscFunctionBegin;
9957   PetscValidType(F, 1);
9958   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9959   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9960   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9961   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9962   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9963     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9964   } else {
9965     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9966   }
9967   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9968   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9969   PetscFunctionReturn(PETSC_SUCCESS);
9970 }
9971 
9972 /*@
9973   MatPtAP - Creates the matrix product $C = P^T * A * P$
9974 
9975   Neighbor-wise Collective
9976 
9977   Input Parameters:
9978 + A     - the matrix
9979 . P     - the projection matrix
9980 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9981 - 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
9982           if the result is a dense matrix this is irrelevant
9983 
9984   Output Parameter:
9985 . C - the product matrix
9986 
9987   Level: intermediate
9988 
9989   Notes:
9990   C will be created and must be destroyed by the user with `MatDestroy()`.
9991 
9992   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9993 
9994   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
9995 
9996   Developer Note:
9997   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9998 
9999 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10000 @*/
10001 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10002 {
10003   PetscFunctionBegin;
10004   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10005   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10006 
10007   if (scall == MAT_INITIAL_MATRIX) {
10008     PetscCall(MatProductCreate(A, P, NULL, C));
10009     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10010     PetscCall(MatProductSetAlgorithm(*C, "default"));
10011     PetscCall(MatProductSetFill(*C, fill));
10012 
10013     (*C)->product->api_user = PETSC_TRUE;
10014     PetscCall(MatProductSetFromOptions(*C));
10015     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);
10016     PetscCall(MatProductSymbolic(*C));
10017   } else { /* scall == MAT_REUSE_MATRIX */
10018     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10019   }
10020 
10021   PetscCall(MatProductNumeric(*C));
10022   (*C)->symmetric = A->symmetric;
10023   (*C)->spd       = A->spd;
10024   PetscFunctionReturn(PETSC_SUCCESS);
10025 }
10026 
10027 /*@
10028   MatRARt - Creates the matrix product $C = R * A * R^T$
10029 
10030   Neighbor-wise Collective
10031 
10032   Input Parameters:
10033 + A     - the matrix
10034 . R     - the projection matrix
10035 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10036 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10037           if the result is a dense matrix this is irrelevant
10038 
10039   Output Parameter:
10040 . C - the product matrix
10041 
10042   Level: intermediate
10043 
10044   Notes:
10045   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10046 
10047   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10048 
10049   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10050   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10051   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10052   We recommend using `MatPtAP()` when possible.
10053 
10054   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10055 
10056 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10057 @*/
10058 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10059 {
10060   PetscFunctionBegin;
10061   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10062   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10063 
10064   if (scall == MAT_INITIAL_MATRIX) {
10065     PetscCall(MatProductCreate(A, R, NULL, C));
10066     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10067     PetscCall(MatProductSetAlgorithm(*C, "default"));
10068     PetscCall(MatProductSetFill(*C, fill));
10069 
10070     (*C)->product->api_user = PETSC_TRUE;
10071     PetscCall(MatProductSetFromOptions(*C));
10072     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);
10073     PetscCall(MatProductSymbolic(*C));
10074   } else { /* scall == MAT_REUSE_MATRIX */
10075     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10076   }
10077 
10078   PetscCall(MatProductNumeric(*C));
10079   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10080   PetscFunctionReturn(PETSC_SUCCESS);
10081 }
10082 
10083 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10084 {
10085   PetscBool flg = PETSC_TRUE;
10086 
10087   PetscFunctionBegin;
10088   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10089   if (scall == MAT_INITIAL_MATRIX) {
10090     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10091     PetscCall(MatProductCreate(A, B, NULL, C));
10092     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10093     PetscCall(MatProductSetFill(*C, fill));
10094   } else { /* scall == MAT_REUSE_MATRIX */
10095     Mat_Product *product = (*C)->product;
10096 
10097     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10098     if (flg && product && product->type != ptype) {
10099       PetscCall(MatProductClear(*C));
10100       product = NULL;
10101     }
10102     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10103     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10104       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10105       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10106       product        = (*C)->product;
10107       product->fill  = fill;
10108       product->clear = PETSC_TRUE;
10109     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10110       flg = PETSC_FALSE;
10111       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10112     }
10113   }
10114   if (flg) {
10115     (*C)->product->api_user = PETSC_TRUE;
10116     PetscCall(MatProductSetType(*C, ptype));
10117     PetscCall(MatProductSetFromOptions(*C));
10118     PetscCall(MatProductSymbolic(*C));
10119   }
10120   PetscCall(MatProductNumeric(*C));
10121   PetscFunctionReturn(PETSC_SUCCESS);
10122 }
10123 
10124 /*@
10125   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10126 
10127   Neighbor-wise Collective
10128 
10129   Input Parameters:
10130 + A     - the left matrix
10131 . B     - the right matrix
10132 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10133 - 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
10134           if the result is a dense matrix this is irrelevant
10135 
10136   Output Parameter:
10137 . C - the product matrix
10138 
10139   Notes:
10140   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10141 
10142   `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
10143   call to this function with `MAT_INITIAL_MATRIX`.
10144 
10145   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10146 
10147   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`,
10148   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10149 
10150   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10151 
10152   Example of Usage:
10153 .vb
10154      MatProductCreate(A,B,NULL,&C);
10155      MatProductSetType(C,MATPRODUCT_AB);
10156      MatProductSymbolic(C);
10157      MatProductNumeric(C); // compute C=A * B
10158      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10159      MatProductNumeric(C);
10160      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10161      MatProductNumeric(C);
10162 .ve
10163 
10164   Level: intermediate
10165 
10166 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10167 @*/
10168 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10169 {
10170   PetscFunctionBegin;
10171   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10172   PetscFunctionReturn(PETSC_SUCCESS);
10173 }
10174 
10175 /*@
10176   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10177 
10178   Neighbor-wise Collective
10179 
10180   Input Parameters:
10181 + A     - the left matrix
10182 . B     - the right matrix
10183 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10184 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10185 
10186   Output Parameter:
10187 . C - the product matrix
10188 
10189   Options Database Key:
10190 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10191               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10192               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10193 
10194   Level: intermediate
10195 
10196   Notes:
10197   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10198 
10199   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10200 
10201   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10202   actually needed.
10203 
10204   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10205   and for pairs of `MATMPIDENSE` matrices.
10206 
10207   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10208 
10209   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10210 
10211 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10212 @*/
10213 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10214 {
10215   PetscFunctionBegin;
10216   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10217   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10218   PetscFunctionReturn(PETSC_SUCCESS);
10219 }
10220 
10221 /*@
10222   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10223 
10224   Neighbor-wise Collective
10225 
10226   Input Parameters:
10227 + A     - the left matrix
10228 . B     - the right matrix
10229 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10230 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10231 
10232   Output Parameter:
10233 . C - the product matrix
10234 
10235   Level: intermediate
10236 
10237   Notes:
10238   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10239 
10240   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10241 
10242   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10243 
10244   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10245   actually needed.
10246 
10247   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10248   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10249 
10250   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10251 
10252 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10253 @*/
10254 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10255 {
10256   PetscFunctionBegin;
10257   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10258   PetscFunctionReturn(PETSC_SUCCESS);
10259 }
10260 
10261 /*@
10262   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10263 
10264   Neighbor-wise Collective
10265 
10266   Input Parameters:
10267 + A     - the left matrix
10268 . B     - the middle matrix
10269 . C     - the right matrix
10270 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10271 - 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
10272           if the result is a dense matrix this is irrelevant
10273 
10274   Output Parameter:
10275 . D - the product matrix
10276 
10277   Level: intermediate
10278 
10279   Notes:
10280   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10281 
10282   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10283 
10284   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10285 
10286   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10287   actually needed.
10288 
10289   If you have many matrices with the same non-zero structure to multiply, you
10290   should use `MAT_REUSE_MATRIX` in all calls but the first
10291 
10292   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10293 
10294 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10295 @*/
10296 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10297 {
10298   PetscFunctionBegin;
10299   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10300   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10301 
10302   if (scall == MAT_INITIAL_MATRIX) {
10303     PetscCall(MatProductCreate(A, B, C, D));
10304     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10305     PetscCall(MatProductSetAlgorithm(*D, "default"));
10306     PetscCall(MatProductSetFill(*D, fill));
10307 
10308     (*D)->product->api_user = PETSC_TRUE;
10309     PetscCall(MatProductSetFromOptions(*D));
10310     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,
10311                ((PetscObject)C)->type_name);
10312     PetscCall(MatProductSymbolic(*D));
10313   } else { /* user may change input matrices when REUSE */
10314     PetscCall(MatProductReplaceMats(A, B, C, *D));
10315   }
10316   PetscCall(MatProductNumeric(*D));
10317   PetscFunctionReturn(PETSC_SUCCESS);
10318 }
10319 
10320 /*@
10321   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10322 
10323   Collective
10324 
10325   Input Parameters:
10326 + mat      - the matrix
10327 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10328 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10329 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10330 
10331   Output Parameter:
10332 . matredundant - redundant matrix
10333 
10334   Level: advanced
10335 
10336   Notes:
10337   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10338   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10339 
10340   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10341   calling it.
10342 
10343   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10344 
10345 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10346 @*/
10347 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10348 {
10349   MPI_Comm       comm;
10350   PetscMPIInt    size;
10351   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10352   Mat_Redundant *redund     = NULL;
10353   PetscSubcomm   psubcomm   = NULL;
10354   MPI_Comm       subcomm_in = subcomm;
10355   Mat           *matseq;
10356   IS             isrow, iscol;
10357   PetscBool      newsubcomm = PETSC_FALSE;
10358 
10359   PetscFunctionBegin;
10360   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10361   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10362     PetscAssertPointer(*matredundant, 5);
10363     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10364   }
10365 
10366   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10367   if (size == 1 || nsubcomm == 1) {
10368     if (reuse == MAT_INITIAL_MATRIX) {
10369       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10370     } else {
10371       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");
10372       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10373     }
10374     PetscFunctionReturn(PETSC_SUCCESS);
10375   }
10376 
10377   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10378   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10379   MatCheckPreallocated(mat, 1);
10380 
10381   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10382   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10383     /* create psubcomm, then get subcomm */
10384     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10385     PetscCallMPI(MPI_Comm_size(comm, &size));
10386     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10387 
10388     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10389     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10390     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10391     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10392     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10393     newsubcomm = PETSC_TRUE;
10394     PetscCall(PetscSubcommDestroy(&psubcomm));
10395   }
10396 
10397   /* get isrow, iscol and a local sequential matrix matseq[0] */
10398   if (reuse == MAT_INITIAL_MATRIX) {
10399     mloc_sub = PETSC_DECIDE;
10400     nloc_sub = PETSC_DECIDE;
10401     if (bs < 1) {
10402       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10403       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10404     } else {
10405       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10406       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10407     }
10408     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10409     rstart = rend - mloc_sub;
10410     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10411     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10412     PetscCall(ISSetIdentity(iscol));
10413   } else { /* reuse == MAT_REUSE_MATRIX */
10414     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");
10415     /* retrieve subcomm */
10416     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10417     redund = (*matredundant)->redundant;
10418     isrow  = redund->isrow;
10419     iscol  = redund->iscol;
10420     matseq = redund->matseq;
10421   }
10422   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10423 
10424   /* get matredundant over subcomm */
10425   if (reuse == MAT_INITIAL_MATRIX) {
10426     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10427 
10428     /* create a supporting struct and attach it to C for reuse */
10429     PetscCall(PetscNew(&redund));
10430     (*matredundant)->redundant = redund;
10431     redund->isrow              = isrow;
10432     redund->iscol              = iscol;
10433     redund->matseq             = matseq;
10434     if (newsubcomm) {
10435       redund->subcomm = subcomm;
10436     } else {
10437       redund->subcomm = MPI_COMM_NULL;
10438     }
10439   } else {
10440     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10441   }
10442 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10443   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10444     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10445     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10446   }
10447 #endif
10448   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10449   PetscFunctionReturn(PETSC_SUCCESS);
10450 }
10451 
10452 /*@C
10453   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10454   a given `Mat`. Each submatrix can span multiple procs.
10455 
10456   Collective
10457 
10458   Input Parameters:
10459 + mat     - the matrix
10460 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10461 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10462 
10463   Output Parameter:
10464 . subMat - parallel sub-matrices each spanning a given `subcomm`
10465 
10466   Level: advanced
10467 
10468   Notes:
10469   The submatrix partition across processors is dictated by `subComm` a
10470   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10471   is not restricted to be grouped with consecutive original MPI processes.
10472 
10473   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10474   map directly to the layout of the original matrix [wrt the local
10475   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10476   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10477   the `subMat`. However the offDiagMat looses some columns - and this is
10478   reconstructed with `MatSetValues()`
10479 
10480   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10481 
10482 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10483 @*/
10484 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10485 {
10486   PetscMPIInt commsize, subCommSize;
10487 
10488   PetscFunctionBegin;
10489   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10490   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10491   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10492 
10493   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");
10494   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10495   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10496   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10497   PetscFunctionReturn(PETSC_SUCCESS);
10498 }
10499 
10500 /*@
10501   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10502 
10503   Not Collective
10504 
10505   Input Parameters:
10506 + mat   - matrix to extract local submatrix from
10507 . isrow - local row indices for submatrix
10508 - iscol - local column indices for submatrix
10509 
10510   Output Parameter:
10511 . submat - the submatrix
10512 
10513   Level: intermediate
10514 
10515   Notes:
10516   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10517 
10518   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10519   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10520 
10521   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10522   `MatSetValuesBlockedLocal()` will also be implemented.
10523 
10524   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10525   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10526 
10527 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10528 @*/
10529 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10530 {
10531   PetscFunctionBegin;
10532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10533   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10534   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10535   PetscCheckSameComm(isrow, 2, iscol, 3);
10536   PetscAssertPointer(submat, 4);
10537   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10538 
10539   if (mat->ops->getlocalsubmatrix) {
10540     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10541   } else {
10542     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10543   }
10544   PetscFunctionReturn(PETSC_SUCCESS);
10545 }
10546 
10547 /*@
10548   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10549 
10550   Not Collective
10551 
10552   Input Parameters:
10553 + mat    - matrix to extract local submatrix from
10554 . isrow  - local row indices for submatrix
10555 . iscol  - local column indices for submatrix
10556 - submat - the submatrix
10557 
10558   Level: intermediate
10559 
10560 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10561 @*/
10562 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10563 {
10564   PetscFunctionBegin;
10565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10566   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10567   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10568   PetscCheckSameComm(isrow, 2, iscol, 3);
10569   PetscAssertPointer(submat, 4);
10570   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10571 
10572   if (mat->ops->restorelocalsubmatrix) {
10573     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10574   } else {
10575     PetscCall(MatDestroy(submat));
10576   }
10577   *submat = NULL;
10578   PetscFunctionReturn(PETSC_SUCCESS);
10579 }
10580 
10581 /*@
10582   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10583 
10584   Collective
10585 
10586   Input Parameter:
10587 . mat - the matrix
10588 
10589   Output Parameter:
10590 . is - if any rows have zero diagonals this contains the list of them
10591 
10592   Level: developer
10593 
10594 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10595 @*/
10596 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10597 {
10598   PetscFunctionBegin;
10599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10600   PetscValidType(mat, 1);
10601   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10602   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10603 
10604   if (!mat->ops->findzerodiagonals) {
10605     Vec                diag;
10606     const PetscScalar *a;
10607     PetscInt          *rows;
10608     PetscInt           rStart, rEnd, r, nrow = 0;
10609 
10610     PetscCall(MatCreateVecs(mat, &diag, NULL));
10611     PetscCall(MatGetDiagonal(mat, diag));
10612     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10613     PetscCall(VecGetArrayRead(diag, &a));
10614     for (r = 0; r < rEnd - rStart; ++r)
10615       if (a[r] == 0.0) ++nrow;
10616     PetscCall(PetscMalloc1(nrow, &rows));
10617     nrow = 0;
10618     for (r = 0; r < rEnd - rStart; ++r)
10619       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10620     PetscCall(VecRestoreArrayRead(diag, &a));
10621     PetscCall(VecDestroy(&diag));
10622     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10623   } else {
10624     PetscUseTypeMethod(mat, findzerodiagonals, is);
10625   }
10626   PetscFunctionReturn(PETSC_SUCCESS);
10627 }
10628 
10629 /*@
10630   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10631 
10632   Collective
10633 
10634   Input Parameter:
10635 . mat - the matrix
10636 
10637   Output Parameter:
10638 . is - contains the list of rows with off block diagonal entries
10639 
10640   Level: developer
10641 
10642 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10643 @*/
10644 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10645 {
10646   PetscFunctionBegin;
10647   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10648   PetscValidType(mat, 1);
10649   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10650   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10651 
10652   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10653   PetscFunctionReturn(PETSC_SUCCESS);
10654 }
10655 
10656 /*@C
10657   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10658 
10659   Collective; No Fortran Support
10660 
10661   Input Parameter:
10662 . mat - the matrix
10663 
10664   Output Parameter:
10665 . values - the block inverses in column major order (FORTRAN-like)
10666 
10667   Level: advanced
10668 
10669   Notes:
10670   The size of the blocks is determined by the block size of the matrix.
10671 
10672   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10673 
10674   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10675 
10676 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10677 @*/
10678 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10679 {
10680   PetscFunctionBegin;
10681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10682   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10683   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10684   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10685   PetscFunctionReturn(PETSC_SUCCESS);
10686 }
10687 
10688 /*@
10689   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10690 
10691   Collective; No Fortran Support
10692 
10693   Input Parameters:
10694 + mat     - the matrix
10695 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10696 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10697 
10698   Output Parameter:
10699 . values - the block inverses in column major order (FORTRAN-like)
10700 
10701   Level: advanced
10702 
10703   Notes:
10704   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10705 
10706   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10707 
10708 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10709 @*/
10710 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10711 {
10712   PetscFunctionBegin;
10713   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10714   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10715   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10716   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10717   PetscFunctionReturn(PETSC_SUCCESS);
10718 }
10719 
10720 /*@
10721   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10722 
10723   Collective
10724 
10725   Input Parameters:
10726 + A - the matrix
10727 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10728 
10729   Level: advanced
10730 
10731   Note:
10732   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10733 
10734 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10735 @*/
10736 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10737 {
10738   const PetscScalar *vals;
10739   PetscInt          *dnnz;
10740   PetscInt           m, rstart, rend, bs, i, j;
10741 
10742   PetscFunctionBegin;
10743   PetscCall(MatInvertBlockDiagonal(A, &vals));
10744   PetscCall(MatGetBlockSize(A, &bs));
10745   PetscCall(MatGetLocalSize(A, &m, NULL));
10746   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10747   PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs));
10748   PetscCall(PetscMalloc1(m / bs, &dnnz));
10749   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10750   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10751   PetscCall(PetscFree(dnnz));
10752   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10753   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10754   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10755   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10756   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10757   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10758   PetscFunctionReturn(PETSC_SUCCESS);
10759 }
10760 
10761 /*@
10762   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10763   via `MatTransposeColoringCreate()`.
10764 
10765   Collective
10766 
10767   Input Parameter:
10768 . c - coloring context
10769 
10770   Level: intermediate
10771 
10772 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10773 @*/
10774 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10775 {
10776   MatTransposeColoring matcolor = *c;
10777 
10778   PetscFunctionBegin;
10779   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10780   if (--((PetscObject)matcolor)->refct > 0) {
10781     matcolor = NULL;
10782     PetscFunctionReturn(PETSC_SUCCESS);
10783   }
10784 
10785   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10786   PetscCall(PetscFree(matcolor->rows));
10787   PetscCall(PetscFree(matcolor->den2sp));
10788   PetscCall(PetscFree(matcolor->colorforcol));
10789   PetscCall(PetscFree(matcolor->columns));
10790   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10791   PetscCall(PetscHeaderDestroy(c));
10792   PetscFunctionReturn(PETSC_SUCCESS);
10793 }
10794 
10795 /*@
10796   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10797   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10798   `MatTransposeColoring` to sparse `B`.
10799 
10800   Collective
10801 
10802   Input Parameters:
10803 + coloring - coloring context created with `MatTransposeColoringCreate()`
10804 - B        - sparse matrix
10805 
10806   Output Parameter:
10807 . Btdense - dense matrix $B^T$
10808 
10809   Level: developer
10810 
10811   Note:
10812   These are used internally for some implementations of `MatRARt()`
10813 
10814 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10815 @*/
10816 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10817 {
10818   PetscFunctionBegin;
10819   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10820   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10821   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10822 
10823   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10824   PetscFunctionReturn(PETSC_SUCCESS);
10825 }
10826 
10827 /*@
10828   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10829   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10830   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10831   $C_{sp}$ from $C_{den}$.
10832 
10833   Collective
10834 
10835   Input Parameters:
10836 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10837 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10838 
10839   Output Parameter:
10840 . Csp - sparse matrix
10841 
10842   Level: developer
10843 
10844   Note:
10845   These are used internally for some implementations of `MatRARt()`
10846 
10847 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10848 @*/
10849 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10850 {
10851   PetscFunctionBegin;
10852   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10853   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10854   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10855 
10856   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10857   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10858   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10859   PetscFunctionReturn(PETSC_SUCCESS);
10860 }
10861 
10862 /*@
10863   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10864 
10865   Collective
10866 
10867   Input Parameters:
10868 + mat        - the matrix product C
10869 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10870 
10871   Output Parameter:
10872 . color - the new coloring context
10873 
10874   Level: intermediate
10875 
10876 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10877           `MatTransColoringApplyDenToSp()`
10878 @*/
10879 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10880 {
10881   MatTransposeColoring c;
10882   MPI_Comm             comm;
10883 
10884   PetscFunctionBegin;
10885   PetscAssertPointer(color, 3);
10886 
10887   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10888   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10889   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10890   c->ctype = iscoloring->ctype;
10891   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10892   *color = c;
10893   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10894   PetscFunctionReturn(PETSC_SUCCESS);
10895 }
10896 
10897 /*@
10898   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10899   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
10900 
10901   Not Collective
10902 
10903   Input Parameter:
10904 . mat - the matrix
10905 
10906   Output Parameter:
10907 . state - the current state
10908 
10909   Level: intermediate
10910 
10911   Notes:
10912   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10913   different matrices
10914 
10915   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10916 
10917   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10918 
10919 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10920 @*/
10921 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10922 {
10923   PetscFunctionBegin;
10924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10925   *state = mat->nonzerostate;
10926   PetscFunctionReturn(PETSC_SUCCESS);
10927 }
10928 
10929 /*@
10930   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10931   matrices from each processor
10932 
10933   Collective
10934 
10935   Input Parameters:
10936 + comm   - the communicators the parallel matrix will live on
10937 . seqmat - the input sequential matrices
10938 . n      - number of local columns (or `PETSC_DECIDE`)
10939 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10940 
10941   Output Parameter:
10942 . mpimat - the parallel matrix generated
10943 
10944   Level: developer
10945 
10946   Note:
10947   The number of columns of the matrix in EACH processor MUST be the same.
10948 
10949 .seealso: [](ch_matrices), `Mat`
10950 @*/
10951 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10952 {
10953   PetscMPIInt size;
10954 
10955   PetscFunctionBegin;
10956   PetscCallMPI(MPI_Comm_size(comm, &size));
10957   if (size == 1) {
10958     if (reuse == MAT_INITIAL_MATRIX) {
10959       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10960     } else {
10961       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10962     }
10963     PetscFunctionReturn(PETSC_SUCCESS);
10964   }
10965 
10966   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");
10967 
10968   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10969   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10970   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10971   PetscFunctionReturn(PETSC_SUCCESS);
10972 }
10973 
10974 /*@
10975   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10976 
10977   Collective
10978 
10979   Input Parameters:
10980 + A - the matrix to create subdomains from
10981 - N - requested number of subdomains
10982 
10983   Output Parameters:
10984 + n   - number of subdomains resulting on this MPI process
10985 - iss - `IS` list with indices of subdomains on this MPI process
10986 
10987   Level: advanced
10988 
10989   Note:
10990   The number of subdomains must be smaller than the communicator size
10991 
10992 .seealso: [](ch_matrices), `Mat`, `IS`
10993 @*/
10994 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10995 {
10996   MPI_Comm    comm, subcomm;
10997   PetscMPIInt size, rank, color;
10998   PetscInt    rstart, rend, k;
10999 
11000   PetscFunctionBegin;
11001   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11002   PetscCallMPI(MPI_Comm_size(comm, &size));
11003   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11004   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);
11005   *n    = 1;
11006   k     = size / N + (size % N > 0); /* There are up to k ranks to a color */
11007   color = rank / k;
11008   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11009   PetscCall(PetscMalloc1(1, iss));
11010   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11011   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11012   PetscCallMPI(MPI_Comm_free(&subcomm));
11013   PetscFunctionReturn(PETSC_SUCCESS);
11014 }
11015 
11016 /*@
11017   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11018 
11019   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11020   If they are not the same, uses `MatMatMatMult()`.
11021 
11022   Once the coarse grid problem is constructed, correct for interpolation operators
11023   that are not of full rank, which can legitimately happen in the case of non-nested
11024   geometric multigrid.
11025 
11026   Input Parameters:
11027 + restrct     - restriction operator
11028 . dA          - fine grid matrix
11029 . interpolate - interpolation operator
11030 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11031 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11032 
11033   Output Parameter:
11034 . A - the Galerkin coarse matrix
11035 
11036   Options Database Key:
11037 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11038 
11039   Level: developer
11040 
11041   Note:
11042   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11043 
11044 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11045 @*/
11046 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11047 {
11048   IS  zerorows;
11049   Vec diag;
11050 
11051   PetscFunctionBegin;
11052   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11053   /* Construct the coarse grid matrix */
11054   if (interpolate == restrct) {
11055     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11056   } else {
11057     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11058   }
11059 
11060   /* If the interpolation matrix is not of full rank, A will have zero rows.
11061      This can legitimately happen in the case of non-nested geometric multigrid.
11062      In that event, we set the rows of the matrix to the rows of the identity,
11063      ignoring the equations (as the RHS will also be zero). */
11064 
11065   PetscCall(MatFindZeroRows(*A, &zerorows));
11066 
11067   if (zerorows != NULL) { /* if there are any zero rows */
11068     PetscCall(MatCreateVecs(*A, &diag, NULL));
11069     PetscCall(MatGetDiagonal(*A, diag));
11070     PetscCall(VecISSet(diag, zerorows, 1.0));
11071     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11072     PetscCall(VecDestroy(&diag));
11073     PetscCall(ISDestroy(&zerorows));
11074   }
11075   PetscFunctionReturn(PETSC_SUCCESS);
11076 }
11077 
11078 /*@C
11079   MatSetOperation - Allows user to set a matrix operation for any matrix type
11080 
11081   Logically Collective
11082 
11083   Input Parameters:
11084 + mat - the matrix
11085 . op  - the name of the operation
11086 - f   - the function that provides the operation
11087 
11088   Level: developer
11089 
11090   Example Usage:
11091 .vb
11092   extern PetscErrorCode usermult(Mat, Vec, Vec);
11093 
11094   PetscCall(MatCreateXXX(comm, ..., &A));
11095   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11096 .ve
11097 
11098   Notes:
11099   See the file `include/petscmat.h` for a complete list of matrix
11100   operations, which all have the form MATOP_<OPERATION>, where
11101   <OPERATION> is the name (in all capital letters) of the
11102   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11103 
11104   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11105   sequence as the usual matrix interface routines, since they
11106   are intended to be accessed via the usual matrix interface
11107   routines, e.g.,
11108 .vb
11109   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11110 .ve
11111 
11112   In particular each function MUST return `PETSC_SUCCESS` on success and
11113   nonzero on failure.
11114 
11115   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11116 
11117 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11118 @*/
11119 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11120 {
11121   PetscFunctionBegin;
11122   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11123   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11124   (((void (**)(void))mat->ops)[op]) = f;
11125   PetscFunctionReturn(PETSC_SUCCESS);
11126 }
11127 
11128 /*@C
11129   MatGetOperation - Gets a matrix operation for any matrix type.
11130 
11131   Not Collective
11132 
11133   Input Parameters:
11134 + mat - the matrix
11135 - op  - the name of the operation
11136 
11137   Output Parameter:
11138 . f - the function that provides the operation
11139 
11140   Level: developer
11141 
11142   Example Usage:
11143 .vb
11144   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11145 
11146   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11147 .ve
11148 
11149   Notes:
11150   See the file include/petscmat.h for a complete list of matrix
11151   operations, which all have the form MATOP_<OPERATION>, where
11152   <OPERATION> is the name (in all capital letters) of the
11153   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11154 
11155   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11156 
11157 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11158 @*/
11159 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11160 {
11161   PetscFunctionBegin;
11162   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11163   *f = (((void (**)(void))mat->ops)[op]);
11164   PetscFunctionReturn(PETSC_SUCCESS);
11165 }
11166 
11167 /*@
11168   MatHasOperation - Determines whether the given matrix supports the particular operation.
11169 
11170   Not Collective
11171 
11172   Input Parameters:
11173 + mat - the matrix
11174 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11175 
11176   Output Parameter:
11177 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11178 
11179   Level: advanced
11180 
11181   Note:
11182   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11183 
11184 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11185 @*/
11186 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11187 {
11188   PetscFunctionBegin;
11189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11190   PetscAssertPointer(has, 3);
11191   if (mat->ops->hasoperation) {
11192     PetscUseTypeMethod(mat, hasoperation, op, has);
11193   } else {
11194     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11195     else {
11196       *has = PETSC_FALSE;
11197       if (op == MATOP_CREATE_SUBMATRIX) {
11198         PetscMPIInt size;
11199 
11200         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11201         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11202       }
11203     }
11204   }
11205   PetscFunctionReturn(PETSC_SUCCESS);
11206 }
11207 
11208 /*@
11209   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11210 
11211   Collective
11212 
11213   Input Parameter:
11214 . mat - the matrix
11215 
11216   Output Parameter:
11217 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11218 
11219   Level: beginner
11220 
11221 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11222 @*/
11223 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11224 {
11225   PetscFunctionBegin;
11226   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11227   PetscValidType(mat, 1);
11228   PetscAssertPointer(cong, 2);
11229   if (!mat->rmap || !mat->cmap) {
11230     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11231     PetscFunctionReturn(PETSC_SUCCESS);
11232   }
11233   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11234     PetscCall(PetscLayoutSetUp(mat->rmap));
11235     PetscCall(PetscLayoutSetUp(mat->cmap));
11236     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11237     if (*cong) mat->congruentlayouts = 1;
11238     else mat->congruentlayouts = 0;
11239   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11240   PetscFunctionReturn(PETSC_SUCCESS);
11241 }
11242 
11243 PetscErrorCode MatSetInf(Mat A)
11244 {
11245   PetscFunctionBegin;
11246   PetscUseTypeMethod(A, setinf);
11247   PetscFunctionReturn(PETSC_SUCCESS);
11248 }
11249 
11250 /*@
11251   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
11252   and possibly removes small values from the graph structure.
11253 
11254   Collective
11255 
11256   Input Parameters:
11257 + A       - the matrix
11258 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11259 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11260 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11261 . num_idx - size of 'index' array
11262 - index   - array of block indices to use for graph strength of connection weight
11263 
11264   Output Parameter:
11265 . graph - the resulting graph
11266 
11267   Level: advanced
11268 
11269 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11270 @*/
11271 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11272 {
11273   PetscFunctionBegin;
11274   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11275   PetscValidType(A, 1);
11276   PetscValidLogicalCollectiveBool(A, scale, 3);
11277   PetscAssertPointer(graph, 7);
11278   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11279   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11280   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11281   PetscFunctionReturn(PETSC_SUCCESS);
11282 }
11283 
11284 /*@
11285   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11286   meaning the same memory is used for the matrix, and no new memory is allocated.
11287 
11288   Collective
11289 
11290   Input Parameters:
11291 + A    - the matrix
11292 - 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
11293 
11294   Level: intermediate
11295 
11296   Developer Note:
11297   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11298   of the arrays in the data structure are unneeded.
11299 
11300 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11301 @*/
11302 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11303 {
11304   PetscFunctionBegin;
11305   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11306   PetscUseTypeMethod(A, eliminatezeros, keep);
11307   PetscFunctionReturn(PETSC_SUCCESS);
11308 }
11309