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