xref: /petsc/src/mat/interface/matrix.c (revision dc9a610e8a93b2ceab441eb761644f4cbb77655c)
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_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51   MatSetRandom - Sets all components of a matrix to random numbers.
52 
53   Logically Collective
54 
55   Input Parameters:
56 + x    - the matrix
57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60   Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67   Level: intermediate
68 
69   Notes:
70   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
71 
72   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
73 
74   It generates an error if used on unassembled sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109   Logically Collective
110 
111   Input Parameter:
112 . mat - the factored matrix
113 
114   Output Parameters:
115 + pivot - the pivot value computed
116 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119   Level: advanced
120 
121   Notes:
122   This routine does not work for factorizations done with external packages.
123 
124   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
130 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
149 . mat - the factored matrix
150 
151   Output Parameter:
152 . err - the error code
153 
154   Level: advanced
155 
156   Note:
157   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172   MatFactorClearError - clears the error code in a factorization
173 
174   Logically Collective
175 
176   Input Parameter:
177 . mat - the factored matrix
178 
179   Level: developer
180 
181   Note:
182   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n, st;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
207     PetscCall(MatGetSize(mat, &N, NULL));
208     PetscCall(MatGetLocalSize(mat, &n, NULL));
209     PetscCall(VecSet(l, 0.0));
210     PetscCall(VecSetRandom(r, NULL));
211     PetscCall(MatMult(mat, r, l));
212     PetscCall(VecGetArrayRead(l, &al));
213   } else { /* nonzero columns */
214     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
215     PetscCall(MatGetSize(mat, NULL, &N));
216     PetscCall(MatGetLocalSize(mat, NULL, &n));
217     PetscCall(VecSet(r, 0.0));
218     PetscCall(VecSetRandom(l, NULL));
219     PetscCall(MatMultTranspose(mat, l, r));
220     PetscCall(VecGetArrayRead(r, &al));
221   }
222   if (tol <= 0.0) {
223     for (i = 0, nz = 0; i < n; i++)
224       if (al[i] != 0.0) nz++;
225   } else {
226     for (i = 0, nz = 0; i < n; i++)
227       if (PetscAbsScalar(al[i]) > tol) nz++;
228   }
229   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
230   if (gnz != N) {
231     PetscInt *nzr;
232     PetscCall(PetscMalloc1(nz, &nzr));
233     if (nz) {
234       if (tol < 0) {
235         for (i = 0, nz = 0; i < n; i++)
236           if (al[i] != 0.0) nzr[nz++] = i + st;
237       } else {
238         for (i = 0, nz = 0; i < n; i++)
239           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
240       }
241     }
242     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
243   } else *nonzero = NULL;
244   if (!cols) { /* nonzero rows */
245     PetscCall(VecRestoreArrayRead(l, &al));
246   } else {
247     PetscCall(VecRestoreArrayRead(r, &al));
248   }
249   PetscCall(VecDestroy(&l));
250   PetscCall(VecDestroy(&r));
251   PetscFunctionReturn(PETSC_SUCCESS);
252 }
253 
254 /*@
255   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
256 
257   Input Parameter:
258 . mat - the matrix
259 
260   Output Parameter:
261 . keptrows - the rows that are not completely zero
262 
263   Level: intermediate
264 
265   Note:
266   `keptrows` is set to `NULL` if all rows are nonzero.
267 
268 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
269  @*/
270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
271 {
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
274   PetscValidType(mat, 1);
275   PetscAssertPointer(keptrows, 2);
276   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
277   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
278   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
279   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
280   PetscFunctionReturn(PETSC_SUCCESS);
281 }
282 
283 /*@
284   MatFindZeroRows - Locate all rows that are completely zero in the matrix
285 
286   Input Parameter:
287 . mat - the matrix
288 
289   Output Parameter:
290 . zerorows - the rows that are completely zero
291 
292   Level: intermediate
293 
294   Note:
295   `zerorows` is set to `NULL` if no rows are zero.
296 
297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
298  @*/
299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
300 {
301   IS       keptrows;
302   PetscInt m, n;
303 
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
306   PetscValidType(mat, 1);
307   PetscAssertPointer(zerorows, 2);
308   PetscCall(MatFindNonzeroRows(mat, &keptrows));
309   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
310      In keeping with this convention, we set zerorows to NULL if there are no zero
311      rows. */
312   if (keptrows == NULL) {
313     *zerorows = NULL;
314   } else {
315     PetscCall(MatGetOwnershipRange(mat, &m, &n));
316     PetscCall(ISComplement(keptrows, m, n, zerorows));
317     PetscCall(ISDestroy(&keptrows));
318   }
319   PetscFunctionReturn(PETSC_SUCCESS);
320 }
321 
322 /*@
323   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
324 
325   Not Collective
326 
327   Input Parameter:
328 . A - the matrix
329 
330   Output Parameter:
331 . a - the diagonal part (which is a SEQUENTIAL matrix)
332 
333   Level: advanced
334 
335   Notes:
336   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
337 
338   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
339 
340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
341 @*/
342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
343 {
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
346   PetscValidType(A, 1);
347   PetscAssertPointer(a, 2);
348   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
349   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
350   else {
351     PetscMPIInt size;
352 
353     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
354     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
355     *a = A;
356   }
357   PetscFunctionReturn(PETSC_SUCCESS);
358 }
359 
360 /*@
361   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
362 
363   Collective
364 
365   Input Parameter:
366 . mat - the matrix
367 
368   Output Parameter:
369 . trace - the sum of the diagonal entries
370 
371   Level: advanced
372 
373 .seealso: [](ch_matrices), `Mat`
374 @*/
375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
376 {
377   Vec diag;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
381   PetscAssertPointer(trace, 2);
382   PetscCall(MatCreateVecs(mat, &diag, NULL));
383   PetscCall(MatGetDiagonal(mat, diag));
384   PetscCall(VecSum(diag, trace));
385   PetscCall(VecDestroy(&diag));
386   PetscFunctionReturn(PETSC_SUCCESS);
387 }
388 
389 /*@
390   MatRealPart - Zeros out the imaginary part of the matrix
391 
392   Logically Collective
393 
394   Input Parameter:
395 . mat - the matrix
396 
397   Level: advanced
398 
399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
400 @*/
401 PetscErrorCode MatRealPart(Mat mat)
402 {
403   PetscFunctionBegin;
404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
405   PetscValidType(mat, 1);
406   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
407   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
408   MatCheckPreallocated(mat, 1);
409   PetscUseTypeMethod(mat, realpart);
410   PetscFunctionReturn(PETSC_SUCCESS);
411 }
412 
413 /*@C
414   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
415 
416   Collective
417 
418   Input Parameter:
419 . mat - the matrix
420 
421   Output Parameters:
422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
423 - ghosts  - the global indices of the ghost points
424 
425   Level: advanced
426 
427   Note:
428   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
429 
430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
431 @*/
432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
433 {
434   PetscFunctionBegin;
435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
436   PetscValidType(mat, 1);
437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
439   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
440   else {
441     if (nghosts) *nghosts = 0;
442     if (ghosts) *ghosts = NULL;
443   }
444   PetscFunctionReturn(PETSC_SUCCESS);
445 }
446 
447 /*@
448   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
449 
450   Logically Collective
451 
452   Input Parameter:
453 . mat - the matrix
454 
455   Level: advanced
456 
457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
458 @*/
459 PetscErrorCode MatImaginaryPart(Mat mat)
460 {
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
463   PetscValidType(mat, 1);
464   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
465   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
466   MatCheckPreallocated(mat, 1);
467   PetscUseTypeMethod(mat, imaginarypart);
468   PetscFunctionReturn(PETSC_SUCCESS);
469 }
470 
471 /*@
472   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
473 
474   Not Collective
475 
476   Input Parameter:
477 . mat - the matrix
478 
479   Output Parameters:
480 + missing - is any diagonal entry missing
481 - dd      - first diagonal entry that is missing (optional) on this process
482 
483   Level: advanced
484 
485   Note:
486   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
487 
488 .seealso: [](ch_matrices), `Mat`
489 @*/
490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
491 {
492   PetscFunctionBegin;
493   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
494   PetscValidType(mat, 1);
495   PetscAssertPointer(missing, 2);
496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
498   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
499   PetscFunctionReturn(PETSC_SUCCESS);
500 }
501 
502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
503 /*@C
504   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
505   for each row that you get to ensure that your application does
506   not bleed memory.
507 
508   Not Collective
509 
510   Input Parameters:
511 + mat - the matrix
512 - row - the row to get
513 
514   Output Parameters:
515 + ncols - if not `NULL`, the number of nonzeros in `row`
516 . cols  - if not `NULL`, the column numbers
517 - vals  - if not `NULL`, the numerical values
518 
519   Level: advanced
520 
521   Notes:
522   This routine is provided for people who need to have direct access
523   to the structure of a matrix.  We hope that we provide enough
524   high-level matrix routines that few users will need it.
525 
526   `MatGetRow()` always returns 0-based column indices, regardless of
527   whether the internal representation is 0-based (default) or 1-based.
528 
529   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
530   not wish to extract these quantities.
531 
532   The user can only examine the values extracted with `MatGetRow()`;
533   the values CANNOT be altered.  To change the matrix entries, one
534   must use `MatSetValues()`.
535 
536   You can only have one call to `MatGetRow()` outstanding for a particular
537   matrix at a time, per processor. `MatGetRow()` can only obtain rows
538   associated with the given processor, it cannot get rows from the
539   other processors; for that we suggest using `MatCreateSubMatrices()`, then
540   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
541   is in the global number of rows.
542 
543   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
544 
545   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
546 
547   Fortran Note:
548   The calling sequence is
549 .vb
550    MatGetRow(matrix,row,ncols,cols,values,ierr)
551          Mat     matrix (input)
552          integer row    (input)
553          integer ncols  (output)
554          integer cols(maxcols) (output)
555          double precision (or double complex) values(maxcols) output
556 .ve
557   where maxcols >= maximum nonzeros in any row of the matrix.
558 
559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
560 @*/
561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
562 {
563   PetscInt incols;
564 
565   PetscFunctionBegin;
566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
567   PetscValidType(mat, 1);
568   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
569   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
570   MatCheckPreallocated(mat, 1);
571   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);
572   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
573   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
574   if (ncols) *ncols = incols;
575   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
576   PetscFunctionReturn(PETSC_SUCCESS);
577 }
578 
579 /*@
580   MatConjugate - replaces the matrix values with their complex conjugates
581 
582   Logically Collective
583 
584   Input Parameter:
585 . mat - the matrix
586 
587   Level: advanced
588 
589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
590 @*/
591 PetscErrorCode MatConjugate(Mat mat)
592 {
593   PetscFunctionBegin;
594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
596   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
597     PetscUseTypeMethod(mat, conjugate);
598     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
599   }
600   PetscFunctionReturn(PETSC_SUCCESS);
601 }
602 
603 /*@C
604   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
605 
606   Not Collective
607 
608   Input Parameters:
609 + mat   - the matrix
610 . row   - the row to get
611 . ncols - the number of nonzeros
612 . cols  - the columns of the nonzeros
613 - vals  - if nonzero the column values
614 
615   Level: advanced
616 
617   Notes:
618   This routine should be called after you have finished examining the entries.
619 
620   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
621   us of the array after it has been restored. If you pass `NULL`, it will
622   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
623 
624   Fortran Notes:
625   The calling sequence is
626 .vb
627    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
628       Mat     matrix (input)
629       integer row    (input)
630       integer ncols  (output)
631       integer cols(maxcols) (output)
632       double precision (or double complex) values(maxcols) output
633 .ve
634   Where maxcols >= maximum nonzeros in any row of the matrix.
635 
636   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
637   before another call to `MatGetRow()` can be made.
638 
639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
640 @*/
641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
642 {
643   PetscFunctionBegin;
644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
645   if (ncols) PetscAssertPointer(ncols, 3);
646   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
647   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
648   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
649   if (ncols) *ncols = 0;
650   if (cols) *cols = NULL;
651   if (vals) *vals = NULL;
652   PetscFunctionReturn(PETSC_SUCCESS);
653 }
654 
655 /*@
656   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
657   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
658 
659   Not Collective
660 
661   Input Parameter:
662 . mat - the matrix
663 
664   Level: advanced
665 
666   Note:
667   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.
668 
669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
670 @*/
671 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
672 {
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
675   PetscValidType(mat, 1);
676   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
677   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
678   MatCheckPreallocated(mat, 1);
679   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
680   PetscUseTypeMethod(mat, getrowuppertriangular);
681   PetscFunctionReturn(PETSC_SUCCESS);
682 }
683 
684 /*@
685   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
686 
687   Not Collective
688 
689   Input Parameter:
690 . mat - the matrix
691 
692   Level: advanced
693 
694   Note:
695   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
696 
697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
698 @*/
699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
700 {
701   PetscFunctionBegin;
702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
703   PetscValidType(mat, 1);
704   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
705   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
706   MatCheckPreallocated(mat, 1);
707   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
708   PetscUseTypeMethod(mat, restorerowuppertriangular);
709   PetscFunctionReturn(PETSC_SUCCESS);
710 }
711 
712 /*@C
713   MatSetOptionsPrefix - Sets the prefix used for searching for all
714   `Mat` options in the database.
715 
716   Logically Collective
717 
718   Input Parameters:
719 + A      - the matrix
720 - prefix - the prefix to prepend to all option names
721 
722   Level: advanced
723 
724   Notes:
725   A hyphen (-) must NOT be given at the beginning of the prefix name.
726   The first character of all runtime options is AUTOMATICALLY the hyphen.
727 
728   This is NOT used for options for the factorization of the matrix. Normally the
729   prefix is automatically passed in from the PC calling the factorization. To set
730   it directly use  `MatSetOptionsPrefixFactor()`
731 
732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
733 @*/
734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
735 {
736   PetscFunctionBegin;
737   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
738   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
739   PetscFunctionReturn(PETSC_SUCCESS);
740 }
741 
742 /*@C
743   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
744   for matrices created with `MatGetFactor()`
745 
746   Logically Collective
747 
748   Input Parameters:
749 + A      - the matrix
750 - prefix - the prefix to prepend to all option names for the factored matrix
751 
752   Level: developer
753 
754   Notes:
755   A hyphen (-) must NOT be given at the beginning of the prefix name.
756   The first character of all runtime options is AUTOMATICALLY the hyphen.
757 
758   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
759   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
760 
761 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
762 @*/
763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
764 {
765   PetscFunctionBegin;
766   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
767   if (prefix) {
768     PetscAssertPointer(prefix, 2);
769     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
770     if (prefix != A->factorprefix) {
771       PetscCall(PetscFree(A->factorprefix));
772       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
773     }
774   } else PetscCall(PetscFree(A->factorprefix));
775   PetscFunctionReturn(PETSC_SUCCESS);
776 }
777 
778 /*@C
779   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
780   for matrices created with `MatGetFactor()`
781 
782   Logically Collective
783 
784   Input Parameters:
785 + A      - the matrix
786 - prefix - the prefix to prepend to all option names for the factored matrix
787 
788   Level: developer
789 
790   Notes:
791   A hyphen (-) must NOT be given at the beginning of the prefix name.
792   The first character of all runtime options is AUTOMATICALLY the hyphen.
793 
794   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
795   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
796 
797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
798           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
799           `MatSetOptionsPrefix()`
800 @*/
801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
802 {
803   size_t len1, len2, new_len;
804 
805   PetscFunctionBegin;
806   PetscValidHeader(A, 1);
807   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
808   if (!A->factorprefix) {
809     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
810     PetscFunctionReturn(PETSC_SUCCESS);
811   }
812   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
813 
814   PetscCall(PetscStrlen(A->factorprefix, &len1));
815   PetscCall(PetscStrlen(prefix, &len2));
816   new_len = len1 + len2 + 1;
817   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
818   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
819   PetscFunctionReturn(PETSC_SUCCESS);
820 }
821 
822 /*@C
823   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
824   matrix options in the database.
825 
826   Logically Collective
827 
828   Input Parameters:
829 + A      - the matrix
830 - prefix - the prefix to prepend to all option names
831 
832   Level: advanced
833 
834   Note:
835   A hyphen (-) must NOT be given at the beginning of the prefix name.
836   The first character of all runtime options is AUTOMATICALLY the hyphen.
837 
838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
839 @*/
840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
841 {
842   PetscFunctionBegin;
843   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
844   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
845   PetscFunctionReturn(PETSC_SUCCESS);
846 }
847 
848 /*@C
849   MatGetOptionsPrefix - Gets the prefix used for searching for all
850   matrix options in the database.
851 
852   Not Collective
853 
854   Input Parameter:
855 . A - the matrix
856 
857   Output Parameter:
858 . prefix - pointer to the prefix string used
859 
860   Level: advanced
861 
862   Fortran Note:
863   The user should pass in a string `prefix` of
864   sufficient length to hold the prefix.
865 
866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
867 @*/
868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
869 {
870   PetscFunctionBegin;
871   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
872   PetscAssertPointer(prefix, 2);
873   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
874   PetscFunctionReturn(PETSC_SUCCESS);
875 }
876 
877 /*@
878   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
879 
880   Collective
881 
882   Input Parameter:
883 . A - the matrix
884 
885   Level: beginner
886 
887   Notes:
888   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
889 
890   Users can reset the preallocation to access the original memory.
891 
892   Currently only supported for  `MATAIJ` matrices.
893 
894 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
895 @*/
896 PetscErrorCode MatResetPreallocation(Mat A)
897 {
898   PetscFunctionBegin;
899   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
900   PetscValidType(A, 1);
901   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
902   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
903   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
904   PetscFunctionReturn(PETSC_SUCCESS);
905 }
906 
907 /*@
908   MatSetUp - Sets up the internal matrix data structures for later use.
909 
910   Collective
911 
912   Input Parameter:
913 . A - the matrix
914 
915   Level: intermediate
916 
917   Notes:
918   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
919   setting values in the matrix.
920 
921   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
922 
923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
924 @*/
925 PetscErrorCode MatSetUp(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   if (!((PetscObject)A)->type_name) {
930     PetscMPIInt size;
931 
932     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
933     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
934   }
935   if (!A->preallocated) PetscTryTypeMethod(A, setup);
936   PetscCall(PetscLayoutSetUp(A->rmap));
937   PetscCall(PetscLayoutSetUp(A->cmap));
938   A->preallocated = PETSC_TRUE;
939   PetscFunctionReturn(PETSC_SUCCESS);
940 }
941 
942 #if defined(PETSC_HAVE_SAWS)
943   #include <petscviewersaws.h>
944 #endif
945 
946 /*
947    If threadsafety is on extraneous matrices may be printed
948 
949    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
950 */
951 #if !defined(PETSC_HAVE_THREADSAFETY)
952 static PetscInt insidematview = 0;
953 #endif
954 
955 /*@C
956   MatViewFromOptions - View properties of the matrix based on options set in the options database
957 
958   Collective
959 
960   Input Parameters:
961 + A    - the matrix
962 . obj  - optional additional object that provides the options prefix to use
963 - name - command line option
964 
965   Options Database Key:
966 . -mat_view [viewertype]:... - the viewer and its options
967 
968   Level: intermediate
969 
970   Note:
971 .vb
972     If no value is provided ascii:stdout is used
973        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
974                                                   for example ascii::ascii_info prints just the information about the object not all details
975                                                   unless :append is given filename opens in write mode, overwriting what was already there
976        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
977        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
978        socket[:port]                             defaults to the standard output port
979        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
980 .ve
981 
982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
983 @*/
984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
985 {
986   PetscFunctionBegin;
987   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
988 #if !defined(PETSC_HAVE_THREADSAFETY)
989   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
990 #endif
991   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
992   PetscFunctionReturn(PETSC_SUCCESS);
993 }
994 
995 /*@C
996   MatView - display information about a matrix in a variety ways
997 
998   Collective
999 
1000   Input Parameters:
1001 + mat    - the matrix
1002 - viewer - visualization context
1003 
1004   Options Database Keys:
1005 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1006 . -mat_view ::ascii_info_detail    - Prints more detailed info
1007 . -mat_view                        - Prints matrix in ASCII format
1008 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1009 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1010 . -display <name>                  - Sets display name (default is host)
1011 . -draw_pause <sec>                - Sets number of seconds to pause after display
1012 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1013 . -viewer_socket_machine <machine> - -
1014 . -viewer_socket_port <port>       - -
1015 . -mat_view binary                 - save matrix to file in binary format
1016 - -viewer_binary_filename <name>   - -
1017 
1018   Level: beginner
1019 
1020   Notes:
1021   The available visualization contexts include
1022 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1023 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1024 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1025 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1026 
1027   The user can open alternative visualization contexts with
1028 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1029 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1030   specified file; corresponding input uses `MatLoad()`
1031 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1032   an X window display
1033 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1034   Currently only the `MATSEQDENSE` and `MATAIJ`
1035   matrix types support the Socket viewer.
1036 
1037   The user can call `PetscViewerPushFormat()` to specify the output
1038   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1039   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1040 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1041 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1042 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1043 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1044   format common among all matrix types
1045 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1046   format (which is in many cases the same as the default)
1047 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1048   size and structure (not the matrix entries)
1049 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1050   the matrix structure
1051 
1052   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1053   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1054 
1055   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1056 
1057   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1058   viewer is used.
1059 
1060   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1061   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1062 
1063   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1064   and then use the following mouse functions.
1065 .vb
1066   left mouse: zoom in
1067   middle mouse: zoom out
1068   right mouse: continue with the simulation
1069 .ve
1070 
1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1072           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1073 @*/
1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1075 {
1076   PetscInt          rows, cols, rbs, cbs;
1077   PetscBool         isascii, isstring, issaws;
1078   PetscViewerFormat format;
1079   PetscMPIInt       size;
1080 
1081   PetscFunctionBegin;
1082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1083   PetscValidType(mat, 1);
1084   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1085   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1086   PetscCheckSameComm(mat, 1, viewer, 2);
1087 
1088   PetscCall(PetscViewerGetFormat(viewer, &format));
1089   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1090   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1091 
1092 #if !defined(PETSC_HAVE_THREADSAFETY)
1093   insidematview++;
1094 #endif
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1097   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1098   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1099 
1100   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1101   if (isascii) {
1102     if (!mat->preallocated) {
1103       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1104 #if !defined(PETSC_HAVE_THREADSAFETY)
1105       insidematview--;
1106 #endif
1107       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1108       PetscFunctionReturn(PETSC_SUCCESS);
1109     }
1110     if (!mat->assembled) {
1111       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1112 #if !defined(PETSC_HAVE_THREADSAFETY)
1113       insidematview--;
1114 #endif
1115       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1116       PetscFunctionReturn(PETSC_SUCCESS);
1117     }
1118     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1119     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1120       MatNullSpace nullsp, transnullsp;
1121 
1122       PetscCall(PetscViewerASCIIPushTab(viewer));
1123       PetscCall(MatGetSize(mat, &rows, &cols));
1124       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1125       if (rbs != 1 || cbs != 1) {
1126         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" : ""));
1127         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1128       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1129       if (mat->factortype) {
1130         MatSolverType solver;
1131         PetscCall(MatFactorGetSolverType(mat, &solver));
1132         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1133       }
1134       if (mat->ops->getinfo) {
1135         MatInfo info;
1136         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1137         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1138         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1139       }
1140       PetscCall(MatGetNullSpace(mat, &nullsp));
1141       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1142       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1143       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1144       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1145       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1146       PetscCall(PetscViewerASCIIPushTab(viewer));
1147       PetscCall(MatProductView(mat, viewer));
1148       PetscCall(PetscViewerASCIIPopTab(viewer));
1149       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1150         IS tmp;
1151 
1152         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1153         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1154         PetscCall(PetscViewerASCIIPushTab(viewer));
1155         PetscCall(ISView(tmp, viewer));
1156         PetscCall(PetscViewerASCIIPopTab(viewer));
1157         PetscCall(ISDestroy(&tmp));
1158       }
1159     }
1160   } else if (issaws) {
1161 #if defined(PETSC_HAVE_SAWS)
1162     PetscMPIInt rank;
1163 
1164     PetscCall(PetscObjectName((PetscObject)mat));
1165     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1166     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1167 #endif
1168   } else if (isstring) {
1169     const char *type;
1170     PetscCall(MatGetType(mat, &type));
1171     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1172     PetscTryTypeMethod(mat, view, viewer);
1173   }
1174   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1175     PetscCall(PetscViewerASCIIPushTab(viewer));
1176     PetscUseTypeMethod(mat, viewnative, viewer);
1177     PetscCall(PetscViewerASCIIPopTab(viewer));
1178   } else if (mat->ops->view) {
1179     PetscCall(PetscViewerASCIIPushTab(viewer));
1180     PetscUseTypeMethod(mat, view, viewer);
1181     PetscCall(PetscViewerASCIIPopTab(viewer));
1182   }
1183   if (isascii) {
1184     PetscCall(PetscViewerGetFormat(viewer, &format));
1185     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1186   }
1187   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1188 #if !defined(PETSC_HAVE_THREADSAFETY)
1189   insidematview--;
1190 #endif
1191   PetscFunctionReturn(PETSC_SUCCESS);
1192 }
1193 
1194 #if defined(PETSC_USE_DEBUG)
1195   #include <../src/sys/totalview/tv_data_display.h>
1196 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1197 {
1198   TV_add_row("Local rows", "int", &mat->rmap->n);
1199   TV_add_row("Local columns", "int", &mat->cmap->n);
1200   TV_add_row("Global rows", "int", &mat->rmap->N);
1201   TV_add_row("Global columns", "int", &mat->cmap->N);
1202   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1203   return TV_format_OK;
1204 }
1205 #endif
1206 
1207 /*@C
1208   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1209   with `MatView()`.  The matrix format is determined from the options database.
1210   Generates a parallel MPI matrix if the communicator has more than one
1211   processor.  The default matrix type is `MATAIJ`.
1212 
1213   Collective
1214 
1215   Input Parameters:
1216 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1217             or some related function before a call to `MatLoad()`
1218 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1219 
1220   Options Database Key:
1221 . -matload_block_size <bs> - set block size
1222 
1223   Level: beginner
1224 
1225   Notes:
1226   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1227   `Mat` before calling this routine if you wish to set it from the options database.
1228 
1229   `MatLoad()` automatically loads into the options database any options
1230   given in the file filename.info where filename is the name of the file
1231   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1232   file will be ignored if you use the -viewer_binary_skip_info option.
1233 
1234   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1235   sets the default matrix type AIJ and sets the local and global sizes.
1236   If type and/or size is already set, then the same are used.
1237 
1238   In parallel, each processor can load a subset of rows (or the
1239   entire matrix).  This routine is especially useful when a large
1240   matrix is stored on disk and only part of it is desired on each
1241   processor.  For example, a parallel solver may access only some of
1242   the rows from each processor.  The algorithm used here reads
1243   relatively small blocks of data rather than reading the entire
1244   matrix and then subsetting it.
1245 
1246   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1247   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1248   or the sequence like
1249 .vb
1250     `PetscViewer` v;
1251     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1252     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1253     `PetscViewerSetFromOptions`(v);
1254     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1255     `PetscViewerFileSetName`(v,"datafile");
1256 .ve
1257   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1258 $ -viewer_type {binary, hdf5}
1259 
1260   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1261   and src/mat/tutorials/ex10.c with the second approach.
1262 
1263   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1264   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1265   Multiple objects, both matrices and vectors, can be stored within the same file.
1266   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1267 
1268   Most users should not need to know the details of the binary storage
1269   format, since `MatLoad()` and `MatView()` completely hide these details.
1270   But for anyone who is interested, the standard binary matrix storage
1271   format is
1272 
1273 .vb
1274     PetscInt    MAT_FILE_CLASSID
1275     PetscInt    number of rows
1276     PetscInt    number of columns
1277     PetscInt    total number of nonzeros
1278     PetscInt    *number nonzeros in each row
1279     PetscInt    *column indices of all nonzeros (starting index is zero)
1280     PetscScalar *values of all nonzeros
1281 .ve
1282   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1283   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
1284   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1285 
1286   PETSc automatically does the byte swapping for
1287   machines that store the bytes reversed. Thus if you write your own binary
1288   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1289   and `PetscBinaryWrite()` to see how this may be done.
1290 
1291   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1292   Each processor's chunk is loaded independently by its owning MPI process.
1293   Multiple objects, both matrices and vectors, can be stored within the same file.
1294   They are looked up by their PetscObject name.
1295 
1296   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1297   by default the same structure and naming of the AIJ arrays and column count
1298   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1299 $    save example.mat A b -v7.3
1300   can be directly read by this routine (see Reference 1 for details).
1301 
1302   Depending on your MATLAB version, this format might be a default,
1303   otherwise you can set it as default in Preferences.
1304 
1305   Unless -nocompression flag is used to save the file in MATLAB,
1306   PETSc must be configured with ZLIB package.
1307 
1308   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1309 
1310   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1311 
1312   Corresponding `MatView()` is not yet implemented.
1313 
1314   The loaded matrix is actually a transpose of the original one in MATLAB,
1315   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1316   With this format, matrix is automatically transposed by PETSc,
1317   unless the matrix is marked as SPD or symmetric
1318   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1319 
1320   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1321 
1322 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1323  @*/
1324 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1325 {
1326   PetscBool flg;
1327 
1328   PetscFunctionBegin;
1329   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1330   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1331 
1332   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1333 
1334   flg = PETSC_FALSE;
1335   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1336   if (flg) {
1337     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1338     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1339   }
1340   flg = PETSC_FALSE;
1341   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1342   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1343 
1344   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1345   PetscUseTypeMethod(mat, load, viewer);
1346   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1347   PetscFunctionReturn(PETSC_SUCCESS);
1348 }
1349 
1350 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1351 {
1352   Mat_Redundant *redund = *redundant;
1353 
1354   PetscFunctionBegin;
1355   if (redund) {
1356     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1357       PetscCall(ISDestroy(&redund->isrow));
1358       PetscCall(ISDestroy(&redund->iscol));
1359       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1360     } else {
1361       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1362       PetscCall(PetscFree(redund->sbuf_j));
1363       PetscCall(PetscFree(redund->sbuf_a));
1364       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1365         PetscCall(PetscFree(redund->rbuf_j[i]));
1366         PetscCall(PetscFree(redund->rbuf_a[i]));
1367       }
1368       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1369     }
1370 
1371     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1372     PetscCall(PetscFree(redund));
1373   }
1374   PetscFunctionReturn(PETSC_SUCCESS);
1375 }
1376 
1377 /*@C
1378   MatDestroy - Frees space taken by a matrix.
1379 
1380   Collective
1381 
1382   Input Parameter:
1383 . A - the matrix
1384 
1385   Level: beginner
1386 
1387   Developer Note:
1388   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1389   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1390   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1391   if changes are needed here.
1392 
1393 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1394 @*/
1395 PetscErrorCode MatDestroy(Mat *A)
1396 {
1397   PetscFunctionBegin;
1398   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1399   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1400   if (--((PetscObject)*A)->refct > 0) {
1401     *A = NULL;
1402     PetscFunctionReturn(PETSC_SUCCESS);
1403   }
1404 
1405   /* if memory was published with SAWs then destroy it */
1406   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1407   PetscTryTypeMethod(*A, destroy);
1408 
1409   PetscCall(PetscFree((*A)->factorprefix));
1410   PetscCall(PetscFree((*A)->defaultvectype));
1411   PetscCall(PetscFree((*A)->defaultrandtype));
1412   PetscCall(PetscFree((*A)->bsizes));
1413   PetscCall(PetscFree((*A)->solvertype));
1414   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1415   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1416   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1417   PetscCall(MatProductClear(*A));
1418   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1419   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1420   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1421   PetscCall(MatDestroy(&(*A)->schur));
1422   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1423   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1424   PetscCall(PetscHeaderDestroy(A));
1425   PetscFunctionReturn(PETSC_SUCCESS);
1426 }
1427 
1428 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1429 /*@C
1430   MatSetValues - Inserts or adds a block of values into a matrix.
1431   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1432   MUST be called after all calls to `MatSetValues()` have been completed.
1433 
1434   Not Collective
1435 
1436   Input Parameters:
1437 + mat  - the matrix
1438 . v    - a logically two-dimensional array of values
1439 . m    - the number of rows
1440 . idxm - the global indices of the rows
1441 . n    - the number of columns
1442 . idxn - the global indices of the columns
1443 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1444 
1445   Level: beginner
1446 
1447   Notes:
1448   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1449 
1450   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1451   options cannot be mixed without intervening calls to the assembly
1452   routines.
1453 
1454   `MatSetValues()` uses 0-based row and column numbers in Fortran
1455   as well as in C.
1456 
1457   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1458   simply ignored. This allows easily inserting element stiffness matrices
1459   with homogeneous Dirichlet boundary conditions that you don't want represented
1460   in the matrix.
1461 
1462   Efficiency Alert:
1463   The routine `MatSetValuesBlocked()` may offer much better efficiency
1464   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1465 
1466   Developer Note:
1467   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1468   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1469 
1470 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1471           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1472 @*/
1473 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1474 {
1475   PetscFunctionBeginHot;
1476   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1477   PetscValidType(mat, 1);
1478   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1479   PetscAssertPointer(idxm, 3);
1480   PetscAssertPointer(idxn, 5);
1481   MatCheckPreallocated(mat, 1);
1482 
1483   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1484   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1485 
1486   if (PetscDefined(USE_DEBUG)) {
1487     PetscInt i, j;
1488 
1489     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1490     if (v) {
1491       for (i = 0; i < m; i++) {
1492         for (j = 0; j < n; j++) {
1493           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1494 #if defined(PETSC_USE_COMPLEX)
1495             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]);
1496 #else
1497             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]);
1498 #endif
1499         }
1500       }
1501     }
1502     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);
1503     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);
1504   }
1505 
1506   if (mat->assembled) {
1507     mat->was_assembled = PETSC_TRUE;
1508     mat->assembled     = PETSC_FALSE;
1509   }
1510   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1511   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1512   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1513   PetscFunctionReturn(PETSC_SUCCESS);
1514 }
1515 
1516 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1517 /*@C
1518   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1519   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1520   MUST be called after all calls to `MatSetValues()` have been completed.
1521 
1522   Not Collective
1523 
1524   Input Parameters:
1525 + mat  - the matrix
1526 . v    - a logically two-dimensional array of values
1527 . ism  - the rows to provide
1528 . isn  - the columns to provide
1529 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1530 
1531   Level: beginner
1532 
1533   Notes:
1534   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1535 
1536   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1537   options cannot be mixed without intervening calls to the assembly
1538   routines.
1539 
1540   `MatSetValues()` uses 0-based row and column numbers in Fortran
1541   as well as in C.
1542 
1543   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1544   simply ignored. This allows easily inserting element stiffness matrices
1545   with homogeneous Dirichlet boundary conditions that you don't want represented
1546   in the matrix.
1547 
1548   Efficiency Alert:
1549   The routine `MatSetValuesBlocked()` may offer much better efficiency
1550   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1551 
1552   This is currently not optimized for any particular `ISType`
1553 
1554   Developer Note:
1555   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1556   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1557 
1558 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1559           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1560 @*/
1561 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1562 {
1563   PetscInt        m, n;
1564   const PetscInt *rows, *cols;
1565 
1566   PetscFunctionBeginHot;
1567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1568   PetscCall(ISGetIndices(ism, &rows));
1569   PetscCall(ISGetIndices(isn, &cols));
1570   PetscCall(ISGetLocalSize(ism, &m));
1571   PetscCall(ISGetLocalSize(isn, &n));
1572   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1573   PetscCall(ISRestoreIndices(ism, &rows));
1574   PetscCall(ISRestoreIndices(isn, &cols));
1575   PetscFunctionReturn(PETSC_SUCCESS);
1576 }
1577 
1578 /*@
1579   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1580   values into a matrix
1581 
1582   Not Collective
1583 
1584   Input Parameters:
1585 + mat - the matrix
1586 . row - the (block) row to set
1587 - v   - a logically two-dimensional array of values
1588 
1589   Level: intermediate
1590 
1591   Notes:
1592   The values, `v`, are column-oriented (for the block version) and sorted
1593 
1594   All the nonzero values in `row` must be provided
1595 
1596   The matrix must have previously had its column indices set, likely by having been assembled.
1597 
1598   `row` must belong to this MPI process
1599 
1600 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1601           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1602 @*/
1603 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1604 {
1605   PetscInt globalrow;
1606 
1607   PetscFunctionBegin;
1608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1609   PetscValidType(mat, 1);
1610   PetscAssertPointer(v, 3);
1611   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1612   PetscCall(MatSetValuesRow(mat, globalrow, v));
1613   PetscFunctionReturn(PETSC_SUCCESS);
1614 }
1615 
1616 /*@
1617   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1618   values into a matrix
1619 
1620   Not Collective
1621 
1622   Input Parameters:
1623 + mat - the matrix
1624 . row - the (block) row to set
1625 - 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
1626 
1627   Level: advanced
1628 
1629   Notes:
1630   The values, `v`, are column-oriented for the block version.
1631 
1632   All the nonzeros in `row` must be provided
1633 
1634   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1635 
1636   `row` must belong to this process
1637 
1638 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1639           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1640 @*/
1641 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1642 {
1643   PetscFunctionBeginHot;
1644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1645   PetscValidType(mat, 1);
1646   MatCheckPreallocated(mat, 1);
1647   PetscAssertPointer(v, 3);
1648   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1649   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1650   mat->insertmode = INSERT_VALUES;
1651 
1652   if (mat->assembled) {
1653     mat->was_assembled = PETSC_TRUE;
1654     mat->assembled     = PETSC_FALSE;
1655   }
1656   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1657   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1658   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1659   PetscFunctionReturn(PETSC_SUCCESS);
1660 }
1661 
1662 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1663 /*@
1664   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1665   Using structured grid indexing
1666 
1667   Not Collective
1668 
1669   Input Parameters:
1670 + mat  - the matrix
1671 . m    - number of rows being entered
1672 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1673 . n    - number of columns being entered
1674 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1675 . v    - a logically two-dimensional array of values
1676 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1677 
1678   Level: beginner
1679 
1680   Notes:
1681   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1682 
1683   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1684   options cannot be mixed without intervening calls to the assembly
1685   routines.
1686 
1687   The grid coordinates are across the entire grid, not just the local portion
1688 
1689   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1690   as well as in C.
1691 
1692   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1693 
1694   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1695   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1696 
1697   The columns and rows in the stencil passed in MUST be contained within the
1698   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1699   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1700   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1701   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1702 
1703   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1704   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1705   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1706   `DM_BOUNDARY_PERIODIC` boundary type.
1707 
1708   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
1709   a single value per point) you can skip filling those indices.
1710 
1711   Inspired by the structured grid interface to the HYPRE package
1712   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1713 
1714   Efficiency Alert:
1715   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1716   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1717 
1718   Fortran Note:
1719   `idxm` and `idxn` should be declared as
1720 $     MatStencil idxm(4,m),idxn(4,n)
1721   and the values inserted using
1722 .vb
1723     idxm(MatStencil_i,1) = i
1724     idxm(MatStencil_j,1) = j
1725     idxm(MatStencil_k,1) = k
1726     idxm(MatStencil_c,1) = c
1727     etc
1728 .ve
1729 
1730 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1731           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1732 @*/
1733 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1734 {
1735   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1736   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1737   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1738 
1739   PetscFunctionBegin;
1740   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1741   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1742   PetscValidType(mat, 1);
1743   PetscAssertPointer(idxm, 3);
1744   PetscAssertPointer(idxn, 5);
1745 
1746   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1747     jdxm = buf;
1748     jdxn = buf + m;
1749   } else {
1750     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1751     jdxm = bufm;
1752     jdxn = bufn;
1753   }
1754   for (i = 0; i < m; i++) {
1755     for (j = 0; j < 3 - sdim; j++) dxm++;
1756     tmp = *dxm++ - starts[0];
1757     for (j = 0; j < dim - 1; j++) {
1758       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1759       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1760     }
1761     if (mat->stencil.noc) dxm++;
1762     jdxm[i] = tmp;
1763   }
1764   for (i = 0; i < n; i++) {
1765     for (j = 0; j < 3 - sdim; j++) dxn++;
1766     tmp = *dxn++ - starts[0];
1767     for (j = 0; j < dim - 1; j++) {
1768       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1769       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1770     }
1771     if (mat->stencil.noc) dxn++;
1772     jdxn[i] = tmp;
1773   }
1774   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1775   PetscCall(PetscFree2(bufm, bufn));
1776   PetscFunctionReturn(PETSC_SUCCESS);
1777 }
1778 
1779 /*@
1780   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1781   Using structured grid indexing
1782 
1783   Not Collective
1784 
1785   Input Parameters:
1786 + mat  - the matrix
1787 . m    - number of rows being entered
1788 . idxm - grid coordinates for matrix rows being entered
1789 . n    - number of columns being entered
1790 . idxn - grid coordinates for matrix columns being entered
1791 . v    - a logically two-dimensional array of values
1792 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1793 
1794   Level: beginner
1795 
1796   Notes:
1797   By default the values, `v`, are row-oriented and unsorted.
1798   See `MatSetOption()` for other options.
1799 
1800   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1801   options cannot be mixed without intervening calls to the assembly
1802   routines.
1803 
1804   The grid coordinates are across the entire grid, not just the local portion
1805 
1806   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1807   as well as in C.
1808 
1809   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1810 
1811   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1812   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1813 
1814   The columns and rows in the stencil passed in MUST be contained within the
1815   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1816   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1817   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1818   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1819 
1820   Negative indices may be passed in idxm and idxn, these rows and columns are
1821   simply ignored. This allows easily inserting element stiffness matrices
1822   with homogeneous Dirichlet boundary conditions that you don't want represented
1823   in the matrix.
1824 
1825   Inspired by the structured grid interface to the HYPRE package
1826   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1827 
1828   Fortran Note:
1829   `idxm` and `idxn` should be declared as
1830 $     MatStencil idxm(4,m),idxn(4,n)
1831   and the values inserted using
1832 .vb
1833     idxm(MatStencil_i,1) = i
1834     idxm(MatStencil_j,1) = j
1835     idxm(MatStencil_k,1) = k
1836    etc
1837 .ve
1838 
1839 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1840           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1841           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1842 @*/
1843 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1844 {
1845   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1846   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1847   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1848 
1849   PetscFunctionBegin;
1850   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1851   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1852   PetscValidType(mat, 1);
1853   PetscAssertPointer(idxm, 3);
1854   PetscAssertPointer(idxn, 5);
1855   PetscAssertPointer(v, 6);
1856 
1857   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1858     jdxm = buf;
1859     jdxn = buf + m;
1860   } else {
1861     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1862     jdxm = bufm;
1863     jdxn = bufn;
1864   }
1865   for (i = 0; i < m; i++) {
1866     for (j = 0; j < 3 - sdim; j++) dxm++;
1867     tmp = *dxm++ - starts[0];
1868     for (j = 0; j < sdim - 1; j++) {
1869       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1870       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1871     }
1872     dxm++;
1873     jdxm[i] = tmp;
1874   }
1875   for (i = 0; i < n; i++) {
1876     for (j = 0; j < 3 - sdim; j++) dxn++;
1877     tmp = *dxn++ - starts[0];
1878     for (j = 0; j < sdim - 1; j++) {
1879       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1880       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1881     }
1882     dxn++;
1883     jdxn[i] = tmp;
1884   }
1885   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1886   PetscCall(PetscFree2(bufm, bufn));
1887   PetscFunctionReturn(PETSC_SUCCESS);
1888 }
1889 
1890 /*@
1891   MatSetStencil - Sets the grid information for setting values into a matrix via
1892   `MatSetValuesStencil()`
1893 
1894   Not Collective
1895 
1896   Input Parameters:
1897 + mat    - the matrix
1898 . dim    - dimension of the grid 1, 2, or 3
1899 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1900 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1901 - dof    - number of degrees of freedom per node
1902 
1903   Level: beginner
1904 
1905   Notes:
1906   Inspired by the structured grid interface to the HYPRE package
1907   (www.llnl.gov/CASC/hyper)
1908 
1909   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1910   user.
1911 
1912 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1913           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1914 @*/
1915 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1916 {
1917   PetscFunctionBegin;
1918   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1919   PetscAssertPointer(dims, 3);
1920   PetscAssertPointer(starts, 4);
1921 
1922   mat->stencil.dim = dim + (dof > 1);
1923   for (PetscInt i = 0; i < dim; i++) {
1924     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1925     mat->stencil.starts[i] = starts[dim - i - 1];
1926   }
1927   mat->stencil.dims[dim]   = dof;
1928   mat->stencil.starts[dim] = 0;
1929   mat->stencil.noc         = (PetscBool)(dof == 1);
1930   PetscFunctionReturn(PETSC_SUCCESS);
1931 }
1932 
1933 /*@C
1934   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1935 
1936   Not Collective
1937 
1938   Input Parameters:
1939 + mat  - the matrix
1940 . v    - a logically two-dimensional array of values
1941 . m    - the number of block rows
1942 . idxm - the global block indices
1943 . n    - the number of block columns
1944 . idxn - the global block indices
1945 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1946 
1947   Level: intermediate
1948 
1949   Notes:
1950   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1951   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1952 
1953   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1954   NOT the total number of rows/columns; for example, if the block size is 2 and
1955   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
1956   The values in `idxm` would be 1 2; that is the first index for each block divided by
1957   the block size.
1958 
1959   You must call `MatSetBlockSize()` when constructing this matrix (before
1960   preallocating it).
1961 
1962   By default the values, `v`, are row-oriented, so the layout of
1963   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1964 
1965   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1966   options cannot be mixed without intervening calls to the assembly
1967   routines.
1968 
1969   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1970   as well as in C.
1971 
1972   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1973   simply ignored. This allows easily inserting element stiffness matrices
1974   with homogeneous Dirichlet boundary conditions that you don't want represented
1975   in the matrix.
1976 
1977   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1978   internal searching must be done to determine where to place the
1979   data in the matrix storage space.  By instead inserting blocks of
1980   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1981   reduced.
1982 
1983   Example:
1984 .vb
1985    Suppose m=n=2 and block size(bs) = 2 The array is
1986 
1987    1  2  | 3  4
1988    5  6  | 7  8
1989    - - - | - - -
1990    9  10 | 11 12
1991    13 14 | 15 16
1992 
1993    v[] should be passed in like
1994    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1995 
1996   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1997    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1998 .ve
1999 
2000 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2001 @*/
2002 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2003 {
2004   PetscFunctionBeginHot;
2005   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2006   PetscValidType(mat, 1);
2007   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2008   PetscAssertPointer(idxm, 3);
2009   PetscAssertPointer(idxn, 5);
2010   MatCheckPreallocated(mat, 1);
2011   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2012   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2013   if (PetscDefined(USE_DEBUG)) {
2014     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2015     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2016   }
2017   if (PetscDefined(USE_DEBUG)) {
2018     PetscInt rbs, cbs, M, N, i;
2019     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2020     PetscCall(MatGetSize(mat, &M, &N));
2021     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
2022     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
2023   }
2024   if (mat->assembled) {
2025     mat->was_assembled = PETSC_TRUE;
2026     mat->assembled     = PETSC_FALSE;
2027   }
2028   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2029   if (mat->ops->setvaluesblocked) {
2030     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2031   } else {
2032     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2033     PetscInt i, j, bs, cbs;
2034 
2035     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2036     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2037       iidxm = buf;
2038       iidxn = buf + m * bs;
2039     } else {
2040       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2041       iidxm = bufr;
2042       iidxn = bufc;
2043     }
2044     for (i = 0; i < m; i++) {
2045       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2046     }
2047     if (m != n || bs != cbs || idxm != idxn) {
2048       for (i = 0; i < n; i++) {
2049         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2050       }
2051     } else iidxn = iidxm;
2052     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2053     PetscCall(PetscFree2(bufr, bufc));
2054   }
2055   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2056   PetscFunctionReturn(PETSC_SUCCESS);
2057 }
2058 
2059 /*@C
2060   MatGetValues - Gets a block of local values from a matrix.
2061 
2062   Not Collective; can only return values that are owned by the give process
2063 
2064   Input Parameters:
2065 + mat  - the matrix
2066 . v    - a logically two-dimensional array for storing the values
2067 . m    - the number of rows
2068 . idxm - the  global indices of the rows
2069 . n    - the number of columns
2070 - idxn - the global indices of the columns
2071 
2072   Level: advanced
2073 
2074   Notes:
2075   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2076   The values, `v`, are then returned in a row-oriented format,
2077   analogous to that used by default in `MatSetValues()`.
2078 
2079   `MatGetValues()` uses 0-based row and column numbers in
2080   Fortran as well as in C.
2081 
2082   `MatGetValues()` requires that the matrix has been assembled
2083   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2084   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2085   without intermediate matrix assembly.
2086 
2087   Negative row or column indices will be ignored and those locations in `v` will be
2088   left unchanged.
2089 
2090   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2091   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2092   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2093 
2094 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2095 @*/
2096 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2097 {
2098   PetscFunctionBegin;
2099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2100   PetscValidType(mat, 1);
2101   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2102   PetscAssertPointer(idxm, 3);
2103   PetscAssertPointer(idxn, 5);
2104   PetscAssertPointer(v, 6);
2105   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2106   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2107   MatCheckPreallocated(mat, 1);
2108 
2109   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2110   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2111   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2112   PetscFunctionReturn(PETSC_SUCCESS);
2113 }
2114 
2115 /*@C
2116   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2117   defined previously by `MatSetLocalToGlobalMapping()`
2118 
2119   Not Collective
2120 
2121   Input Parameters:
2122 + mat  - the matrix
2123 . nrow - number of rows
2124 . irow - the row local indices
2125 . ncol - number of columns
2126 - icol - the column local indices
2127 
2128   Output Parameter:
2129 . y - a logically two-dimensional array of values
2130 
2131   Level: advanced
2132 
2133   Notes:
2134   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2135 
2136   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,
2137   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2138   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2139   with `MatSetLocalToGlobalMapping()`.
2140 
2141   Developer Note:
2142   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2143   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2144 
2145 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2146           `MatSetValuesLocal()`, `MatGetValues()`
2147 @*/
2148 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2149 {
2150   PetscFunctionBeginHot;
2151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2152   PetscValidType(mat, 1);
2153   MatCheckPreallocated(mat, 1);
2154   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2155   PetscAssertPointer(irow, 3);
2156   PetscAssertPointer(icol, 5);
2157   if (PetscDefined(USE_DEBUG)) {
2158     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2159     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2160   }
2161   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2162   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2163   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2164   else {
2165     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2166     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2167       irowm = buf;
2168       icolm = buf + nrow;
2169     } else {
2170       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2171       irowm = bufr;
2172       icolm = bufc;
2173     }
2174     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2175     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2176     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2177     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2178     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2179     PetscCall(PetscFree2(bufr, bufc));
2180   }
2181   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2182   PetscFunctionReturn(PETSC_SUCCESS);
2183 }
2184 
2185 /*@
2186   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2187   the same size. Currently, this can only be called once and creates the given matrix.
2188 
2189   Not Collective
2190 
2191   Input Parameters:
2192 + mat  - the matrix
2193 . nb   - the number of blocks
2194 . bs   - the number of rows (and columns) in each block
2195 . rows - a concatenation of the rows for each block
2196 - v    - a concatenation of logically two-dimensional arrays of values
2197 
2198   Level: advanced
2199 
2200   Notes:
2201   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2202 
2203   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2204 
2205 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2206           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2207 @*/
2208 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2209 {
2210   PetscFunctionBegin;
2211   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2212   PetscValidType(mat, 1);
2213   PetscAssertPointer(rows, 4);
2214   PetscAssertPointer(v, 5);
2215   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2216 
2217   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2218   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2219   else {
2220     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2221   }
2222   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2223   PetscFunctionReturn(PETSC_SUCCESS);
2224 }
2225 
2226 /*@
2227   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2228   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2229   using a local (per-processor) numbering.
2230 
2231   Not Collective
2232 
2233   Input Parameters:
2234 + x        - the matrix
2235 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2236 - cmapping - column mapping
2237 
2238   Level: intermediate
2239 
2240   Note:
2241   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2242 
2243 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2244 @*/
2245 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2246 {
2247   PetscFunctionBegin;
2248   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2249   PetscValidType(x, 1);
2250   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2251   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2252   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2253   else {
2254     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2255     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2256   }
2257   PetscFunctionReturn(PETSC_SUCCESS);
2258 }
2259 
2260 /*@
2261   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2262 
2263   Not Collective
2264 
2265   Input Parameter:
2266 . A - the matrix
2267 
2268   Output Parameters:
2269 + rmapping - row mapping
2270 - cmapping - column mapping
2271 
2272   Level: advanced
2273 
2274 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2275 @*/
2276 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2277 {
2278   PetscFunctionBegin;
2279   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2280   PetscValidType(A, 1);
2281   if (rmapping) {
2282     PetscAssertPointer(rmapping, 2);
2283     *rmapping = A->rmap->mapping;
2284   }
2285   if (cmapping) {
2286     PetscAssertPointer(cmapping, 3);
2287     *cmapping = A->cmap->mapping;
2288   }
2289   PetscFunctionReturn(PETSC_SUCCESS);
2290 }
2291 
2292 /*@
2293   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2294 
2295   Logically Collective
2296 
2297   Input Parameters:
2298 + A    - the matrix
2299 . rmap - row layout
2300 - cmap - column layout
2301 
2302   Level: advanced
2303 
2304   Note:
2305   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2306 
2307 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2308 @*/
2309 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2310 {
2311   PetscFunctionBegin;
2312   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2313   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2314   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2315   PetscFunctionReturn(PETSC_SUCCESS);
2316 }
2317 
2318 /*@
2319   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2320 
2321   Not Collective
2322 
2323   Input Parameter:
2324 . A - the matrix
2325 
2326   Output Parameters:
2327 + rmap - row layout
2328 - cmap - column layout
2329 
2330   Level: advanced
2331 
2332 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2333 @*/
2334 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2335 {
2336   PetscFunctionBegin;
2337   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2338   PetscValidType(A, 1);
2339   if (rmap) {
2340     PetscAssertPointer(rmap, 2);
2341     *rmap = A->rmap;
2342   }
2343   if (cmap) {
2344     PetscAssertPointer(cmap, 3);
2345     *cmap = A->cmap;
2346   }
2347   PetscFunctionReturn(PETSC_SUCCESS);
2348 }
2349 
2350 /*@C
2351   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2352   using a local numbering of the rows and columns.
2353 
2354   Not Collective
2355 
2356   Input Parameters:
2357 + mat  - the matrix
2358 . nrow - number of rows
2359 . irow - the row local indices
2360 . ncol - number of columns
2361 . icol - the column local indices
2362 . y    - a logically two-dimensional array of values
2363 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2364 
2365   Level: intermediate
2366 
2367   Notes:
2368   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2369 
2370   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2371   options cannot be mixed without intervening calls to the assembly
2372   routines.
2373 
2374   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2375   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2376 
2377   Developer Note:
2378   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2379   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2380 
2381 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2382           `MatGetValuesLocal()`
2383 @*/
2384 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2385 {
2386   PetscFunctionBeginHot;
2387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2388   PetscValidType(mat, 1);
2389   MatCheckPreallocated(mat, 1);
2390   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2391   PetscAssertPointer(irow, 3);
2392   PetscAssertPointer(icol, 5);
2393   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2394   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2395   if (PetscDefined(USE_DEBUG)) {
2396     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2397     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2398   }
2399 
2400   if (mat->assembled) {
2401     mat->was_assembled = PETSC_TRUE;
2402     mat->assembled     = PETSC_FALSE;
2403   }
2404   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2405   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2406   else {
2407     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2408     const PetscInt *irowm, *icolm;
2409 
2410     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2411       bufr  = buf;
2412       bufc  = buf + nrow;
2413       irowm = bufr;
2414       icolm = bufc;
2415     } else {
2416       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2417       irowm = bufr;
2418       icolm = bufc;
2419     }
2420     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2421     else irowm = irow;
2422     if (mat->cmap->mapping) {
2423       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2424         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2425       } else icolm = irowm;
2426     } else icolm = icol;
2427     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2428     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2429   }
2430   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2431   PetscFunctionReturn(PETSC_SUCCESS);
2432 }
2433 
2434 /*@C
2435   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2436   using a local ordering of the nodes a block at a time.
2437 
2438   Not Collective
2439 
2440   Input Parameters:
2441 + mat  - the matrix
2442 . nrow - number of rows
2443 . irow - the row local indices
2444 . ncol - number of columns
2445 . icol - the column local indices
2446 . y    - a logically two-dimensional array of values
2447 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2448 
2449   Level: intermediate
2450 
2451   Notes:
2452   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2453   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2454 
2455   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2456   options cannot be mixed without intervening calls to the assembly
2457   routines.
2458 
2459   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2460   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2461 
2462   Developer Note:
2463   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2464   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2465 
2466 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2467           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2468 @*/
2469 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2470 {
2471   PetscFunctionBeginHot;
2472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2473   PetscValidType(mat, 1);
2474   MatCheckPreallocated(mat, 1);
2475   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2476   PetscAssertPointer(irow, 3);
2477   PetscAssertPointer(icol, 5);
2478   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2479   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2480   if (PetscDefined(USE_DEBUG)) {
2481     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2482     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2483   }
2484 
2485   if (mat->assembled) {
2486     mat->was_assembled = PETSC_TRUE;
2487     mat->assembled     = PETSC_FALSE;
2488   }
2489   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2490     PetscInt irbs, rbs;
2491     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2492     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2493     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2494   }
2495   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2496     PetscInt icbs, cbs;
2497     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2498     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2499     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2500   }
2501   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2502   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2503   else {
2504     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2505     const PetscInt *irowm, *icolm;
2506 
2507     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2508       bufr  = buf;
2509       bufc  = buf + nrow;
2510       irowm = bufr;
2511       icolm = bufc;
2512     } else {
2513       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2514       irowm = bufr;
2515       icolm = bufc;
2516     }
2517     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2518     else irowm = irow;
2519     if (mat->cmap->mapping) {
2520       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2521         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2522       } else icolm = irowm;
2523     } else icolm = icol;
2524     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2525     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2526   }
2527   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2528   PetscFunctionReturn(PETSC_SUCCESS);
2529 }
2530 
2531 /*@
2532   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2533 
2534   Collective
2535 
2536   Input Parameters:
2537 + mat - the matrix
2538 - x   - the vector to be multiplied
2539 
2540   Output Parameter:
2541 . y - the result
2542 
2543   Level: developer
2544 
2545   Note:
2546   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2547   call `MatMultDiagonalBlock`(A,y,y).
2548 
2549 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2550 @*/
2551 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2552 {
2553   PetscFunctionBegin;
2554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2555   PetscValidType(mat, 1);
2556   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2557   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2558 
2559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2561   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2562   MatCheckPreallocated(mat, 1);
2563 
2564   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2565   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2566   PetscFunctionReturn(PETSC_SUCCESS);
2567 }
2568 
2569 /*@
2570   MatMult - Computes the matrix-vector product, $y = Ax$.
2571 
2572   Neighbor-wise Collective
2573 
2574   Input Parameters:
2575 + mat - the matrix
2576 - x   - the vector to be multiplied
2577 
2578   Output Parameter:
2579 . y - the result
2580 
2581   Level: beginner
2582 
2583   Note:
2584   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2585   call `MatMult`(A,y,y).
2586 
2587 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2588 @*/
2589 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2590 {
2591   PetscFunctionBegin;
2592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2593   PetscValidType(mat, 1);
2594   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2595   VecCheckAssembled(x);
2596   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2597   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2598   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2599   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2600   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);
2601   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);
2602   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);
2603   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);
2604   PetscCall(VecSetErrorIfLocked(y, 3));
2605   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2606   MatCheckPreallocated(mat, 1);
2607 
2608   PetscCall(VecLockReadPush(x));
2609   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2610   PetscUseTypeMethod(mat, mult, x, y);
2611   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2612   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2613   PetscCall(VecLockReadPop(x));
2614   PetscFunctionReturn(PETSC_SUCCESS);
2615 }
2616 
2617 /*@
2618   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2619 
2620   Neighbor-wise Collective
2621 
2622   Input Parameters:
2623 + mat - the matrix
2624 - x   - the vector to be multiplied
2625 
2626   Output Parameter:
2627 . y - the result
2628 
2629   Level: beginner
2630 
2631   Notes:
2632   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2633   call `MatMultTranspose`(A,y,y).
2634 
2635   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2636   use `MatMultHermitianTranspose()`
2637 
2638 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2639 @*/
2640 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2641 {
2642   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2643 
2644   PetscFunctionBegin;
2645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2646   PetscValidType(mat, 1);
2647   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2648   VecCheckAssembled(x);
2649   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2650 
2651   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2652   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2653   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2654   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);
2655   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);
2656   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);
2657   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);
2658   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2659   MatCheckPreallocated(mat, 1);
2660 
2661   if (!mat->ops->multtranspose) {
2662     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2663     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);
2664   } else op = mat->ops->multtranspose;
2665   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2666   PetscCall(VecLockReadPush(x));
2667   PetscCall((*op)(mat, x, y));
2668   PetscCall(VecLockReadPop(x));
2669   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2670   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2671   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2672   PetscFunctionReturn(PETSC_SUCCESS);
2673 }
2674 
2675 /*@
2676   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2677 
2678   Neighbor-wise Collective
2679 
2680   Input Parameters:
2681 + mat - the matrix
2682 - x   - the vector to be multiplied
2683 
2684   Output Parameter:
2685 . y - the result
2686 
2687   Level: beginner
2688 
2689   Notes:
2690   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2691   call `MatMultHermitianTranspose`(A,y,y).
2692 
2693   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2694 
2695   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2696 
2697 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2698 @*/
2699 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2700 {
2701   PetscFunctionBegin;
2702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2703   PetscValidType(mat, 1);
2704   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2705   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2706 
2707   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2708   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2709   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2710   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);
2711   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);
2712   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);
2713   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);
2714   MatCheckPreallocated(mat, 1);
2715 
2716   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2717 #if defined(PETSC_USE_COMPLEX)
2718   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2719     PetscCall(VecLockReadPush(x));
2720     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2721     else PetscUseTypeMethod(mat, mult, x, y);
2722     PetscCall(VecLockReadPop(x));
2723   } else {
2724     Vec w;
2725     PetscCall(VecDuplicate(x, &w));
2726     PetscCall(VecCopy(x, w));
2727     PetscCall(VecConjugate(w));
2728     PetscCall(MatMultTranspose(mat, w, y));
2729     PetscCall(VecDestroy(&w));
2730     PetscCall(VecConjugate(y));
2731   }
2732   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2733 #else
2734   PetscCall(MatMultTranspose(mat, x, y));
2735 #endif
2736   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2737   PetscFunctionReturn(PETSC_SUCCESS);
2738 }
2739 
2740 /*@
2741   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2742 
2743   Neighbor-wise Collective
2744 
2745   Input Parameters:
2746 + mat - the matrix
2747 . v1  - the vector to be multiplied by `mat`
2748 - v2  - the vector to be added to the result
2749 
2750   Output Parameter:
2751 . v3 - the result
2752 
2753   Level: beginner
2754 
2755   Note:
2756   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2757   call `MatMultAdd`(A,v1,v2,v1).
2758 
2759 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2760 @*/
2761 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2762 {
2763   PetscFunctionBegin;
2764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2765   PetscValidType(mat, 1);
2766   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2767   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2768   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2769 
2770   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2771   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2772   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);
2773   /* 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);
2774      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); */
2775   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);
2776   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);
2777   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2778   MatCheckPreallocated(mat, 1);
2779 
2780   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2781   PetscCall(VecLockReadPush(v1));
2782   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2783   PetscCall(VecLockReadPop(v1));
2784   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2785   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2786   PetscFunctionReturn(PETSC_SUCCESS);
2787 }
2788 
2789 /*@
2790   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2791 
2792   Neighbor-wise Collective
2793 
2794   Input Parameters:
2795 + mat - the matrix
2796 . v1  - the vector to be multiplied by the transpose of the matrix
2797 - v2  - the vector to be added to the result
2798 
2799   Output Parameter:
2800 . v3 - the result
2801 
2802   Level: beginner
2803 
2804   Note:
2805   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2806   call `MatMultTransposeAdd`(A,v1,v2,v1).
2807 
2808 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2809 @*/
2810 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2811 {
2812   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2813 
2814   PetscFunctionBegin;
2815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2816   PetscValidType(mat, 1);
2817   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2818   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2819   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2820 
2821   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2822   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2823   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);
2824   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);
2825   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);
2826   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2827   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2828   MatCheckPreallocated(mat, 1);
2829 
2830   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2831   PetscCall(VecLockReadPush(v1));
2832   PetscCall((*op)(mat, v1, v2, v3));
2833   PetscCall(VecLockReadPop(v1));
2834   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2835   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2836   PetscFunctionReturn(PETSC_SUCCESS);
2837 }
2838 
2839 /*@
2840   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2841 
2842   Neighbor-wise Collective
2843 
2844   Input Parameters:
2845 + mat - the matrix
2846 . v1  - the vector to be multiplied by the Hermitian transpose
2847 - v2  - the vector to be added to the result
2848 
2849   Output Parameter:
2850 . v3 - the result
2851 
2852   Level: beginner
2853 
2854   Note:
2855   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2856   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2857 
2858 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2859 @*/
2860 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2861 {
2862   PetscFunctionBegin;
2863   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2864   PetscValidType(mat, 1);
2865   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2866   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2867   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2868 
2869   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2870   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2871   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2872   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);
2873   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);
2874   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);
2875   MatCheckPreallocated(mat, 1);
2876 
2877   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2878   PetscCall(VecLockReadPush(v1));
2879   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2880   else {
2881     Vec w, z;
2882     PetscCall(VecDuplicate(v1, &w));
2883     PetscCall(VecCopy(v1, w));
2884     PetscCall(VecConjugate(w));
2885     PetscCall(VecDuplicate(v3, &z));
2886     PetscCall(MatMultTranspose(mat, w, z));
2887     PetscCall(VecDestroy(&w));
2888     PetscCall(VecConjugate(z));
2889     if (v2 != v3) {
2890       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2891     } else {
2892       PetscCall(VecAXPY(v3, 1.0, z));
2893     }
2894     PetscCall(VecDestroy(&z));
2895   }
2896   PetscCall(VecLockReadPop(v1));
2897   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2898   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2899   PetscFunctionReturn(PETSC_SUCCESS);
2900 }
2901 
2902 /*@C
2903   MatGetFactorType - gets the type of factorization a matrix is
2904 
2905   Not Collective
2906 
2907   Input Parameter:
2908 . mat - the matrix
2909 
2910   Output Parameter:
2911 . 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`
2912 
2913   Level: intermediate
2914 
2915 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2916           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2917 @*/
2918 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2919 {
2920   PetscFunctionBegin;
2921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2922   PetscValidType(mat, 1);
2923   PetscAssertPointer(t, 2);
2924   *t = mat->factortype;
2925   PetscFunctionReturn(PETSC_SUCCESS);
2926 }
2927 
2928 /*@C
2929   MatSetFactorType - sets the type of factorization a matrix is
2930 
2931   Logically Collective
2932 
2933   Input Parameters:
2934 + mat - the matrix
2935 - 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`
2936 
2937   Level: intermediate
2938 
2939 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2940           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2941 @*/
2942 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2943 {
2944   PetscFunctionBegin;
2945   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2946   PetscValidType(mat, 1);
2947   mat->factortype = t;
2948   PetscFunctionReturn(PETSC_SUCCESS);
2949 }
2950 
2951 /*@C
2952   MatGetInfo - Returns information about matrix storage (number of
2953   nonzeros, memory, etc.).
2954 
2955   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2956 
2957   Input Parameters:
2958 + mat  - the matrix
2959 - 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)
2960 
2961   Output Parameter:
2962 . info - matrix information context
2963 
2964   Options Database Key:
2965 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2966 
2967   Notes:
2968   The `MatInfo` context contains a variety of matrix data, including
2969   number of nonzeros allocated and used, number of mallocs during
2970   matrix assembly, etc.  Additional information for factored matrices
2971   is provided (such as the fill ratio, number of mallocs during
2972   factorization, etc.).
2973 
2974   Example:
2975   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2976   data within the MatInfo context.  For example,
2977 .vb
2978       MatInfo info;
2979       Mat     A;
2980       double  mal, nz_a, nz_u;
2981 
2982       MatGetInfo(A, MAT_LOCAL, &info);
2983       mal  = info.mallocs;
2984       nz_a = info.nz_allocated;
2985 .ve
2986 
2987   Fortran users should declare info as a double precision
2988   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2989   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2990   a complete list of parameter names.
2991 .vb
2992       double  precision info(MAT_INFO_SIZE)
2993       double  precision mal, nz_a
2994       Mat     A
2995       integer ierr
2996 
2997       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2998       mal = info(MAT_INFO_MALLOCS)
2999       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3000 .ve
3001 
3002   Level: intermediate
3003 
3004   Developer Note:
3005   The Fortran interface is not autogenerated as the
3006   interface definition cannot be generated correctly [due to `MatInfo` argument]
3007 
3008 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3009 @*/
3010 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3011 {
3012   PetscFunctionBegin;
3013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3014   PetscValidType(mat, 1);
3015   PetscAssertPointer(info, 3);
3016   MatCheckPreallocated(mat, 1);
3017   PetscUseTypeMethod(mat, getinfo, flag, info);
3018   PetscFunctionReturn(PETSC_SUCCESS);
3019 }
3020 
3021 /*
3022    This is used by external packages where it is not easy to get the info from the actual
3023    matrix factorization.
3024 */
3025 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3026 {
3027   PetscFunctionBegin;
3028   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3029   PetscFunctionReturn(PETSC_SUCCESS);
3030 }
3031 
3032 /*@C
3033   MatLUFactor - Performs in-place LU factorization of matrix.
3034 
3035   Collective
3036 
3037   Input Parameters:
3038 + mat  - the matrix
3039 . row  - row permutation
3040 . col  - column permutation
3041 - info - options for factorization, includes
3042 .vb
3043           fill - expected fill as ratio of original fill.
3044           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3045                    Run with the option -info to determine an optimal value to use
3046 .ve
3047 
3048   Level: developer
3049 
3050   Notes:
3051   Most users should employ the `KSP` interface for linear solvers
3052   instead of working directly with matrix algebra routines such as this.
3053   See, e.g., `KSPCreate()`.
3054 
3055   This changes the state of the matrix to a factored matrix; it cannot be used
3056   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3057 
3058   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3059   when not using `KSP`.
3060 
3061   Developer Note:
3062   The Fortran interface is not autogenerated as the
3063   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3064 
3065 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3066           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3067 @*/
3068 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3069 {
3070   MatFactorInfo tinfo;
3071 
3072   PetscFunctionBegin;
3073   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3074   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3075   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3076   if (info) PetscAssertPointer(info, 4);
3077   PetscValidType(mat, 1);
3078   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3079   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3080   MatCheckPreallocated(mat, 1);
3081   if (!info) {
3082     PetscCall(MatFactorInfoInitialize(&tinfo));
3083     info = &tinfo;
3084   }
3085 
3086   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3087   PetscUseTypeMethod(mat, lufactor, row, col, info);
3088   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3089   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3090   PetscFunctionReturn(PETSC_SUCCESS);
3091 }
3092 
3093 /*@C
3094   MatILUFactor - Performs in-place ILU factorization of matrix.
3095 
3096   Collective
3097 
3098   Input Parameters:
3099 + mat  - the matrix
3100 . row  - row permutation
3101 . col  - column permutation
3102 - info - structure containing
3103 .vb
3104       levels - number of levels of fill.
3105       expected fill - as ratio of original fill.
3106       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3107                 missing diagonal entries)
3108 .ve
3109 
3110   Level: developer
3111 
3112   Notes:
3113   Most users should employ the `KSP` interface for linear solvers
3114   instead of working directly with matrix algebra routines such as this.
3115   See, e.g., `KSPCreate()`.
3116 
3117   Probably really in-place only when level of fill is zero, otherwise allocates
3118   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3119   when not using `KSP`.
3120 
3121   Developer Note:
3122   The Fortran interface is not autogenerated as the
3123   interface definition cannot be generated correctly [due to MatFactorInfo]
3124 
3125 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3126 @*/
3127 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3128 {
3129   PetscFunctionBegin;
3130   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3131   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3132   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3133   PetscAssertPointer(info, 4);
3134   PetscValidType(mat, 1);
3135   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3136   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3137   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3138   MatCheckPreallocated(mat, 1);
3139 
3140   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3141   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3142   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3143   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3144   PetscFunctionReturn(PETSC_SUCCESS);
3145 }
3146 
3147 /*@C
3148   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3149   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3150 
3151   Collective
3152 
3153   Input Parameters:
3154 + fact - the factor matrix obtained with `MatGetFactor()`
3155 . mat  - the matrix
3156 . row  - the row permutation
3157 . col  - the column permutation
3158 - info - options for factorization, includes
3159 .vb
3160           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3161           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3162 .ve
3163 
3164   Level: developer
3165 
3166   Notes:
3167   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3168 
3169   Most users should employ the simplified `KSP` interface for linear solvers
3170   instead of working directly with matrix algebra routines such as this.
3171   See, e.g., `KSPCreate()`.
3172 
3173   Developer Note:
3174   The Fortran interface is not autogenerated as the
3175   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3176 
3177 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3178 @*/
3179 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3180 {
3181   MatFactorInfo tinfo;
3182 
3183   PetscFunctionBegin;
3184   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3185   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3186   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3187   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3188   if (info) PetscAssertPointer(info, 5);
3189   PetscValidType(fact, 1);
3190   PetscValidType(mat, 2);
3191   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3192   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3193   MatCheckPreallocated(mat, 2);
3194   if (!info) {
3195     PetscCall(MatFactorInfoInitialize(&tinfo));
3196     info = &tinfo;
3197   }
3198 
3199   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3200   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3201   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3202   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3203   PetscFunctionReturn(PETSC_SUCCESS);
3204 }
3205 
3206 /*@C
3207   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3208   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3209 
3210   Collective
3211 
3212   Input Parameters:
3213 + fact - the factor matrix obtained with `MatGetFactor()`
3214 . mat  - the matrix
3215 - info - options for factorization
3216 
3217   Level: developer
3218 
3219   Notes:
3220   See `MatLUFactor()` for in-place factorization.  See
3221   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3222 
3223   Most users should employ the `KSP` interface for linear solvers
3224   instead of working directly with matrix algebra routines such as this.
3225   See, e.g., `KSPCreate()`.
3226 
3227   Developer Note:
3228   The Fortran interface is not autogenerated as the
3229   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3230 
3231 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3232 @*/
3233 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3234 {
3235   MatFactorInfo tinfo;
3236 
3237   PetscFunctionBegin;
3238   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3239   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3240   PetscValidType(fact, 1);
3241   PetscValidType(mat, 2);
3242   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3243   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,
3244              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3245 
3246   MatCheckPreallocated(mat, 2);
3247   if (!info) {
3248     PetscCall(MatFactorInfoInitialize(&tinfo));
3249     info = &tinfo;
3250   }
3251 
3252   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3253   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3254   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3255   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3256   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3257   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3258   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3259   PetscFunctionReturn(PETSC_SUCCESS);
3260 }
3261 
3262 /*@C
3263   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3264   symmetric matrix.
3265 
3266   Collective
3267 
3268   Input Parameters:
3269 + mat  - the matrix
3270 . perm - row and column permutations
3271 - info - expected fill as ratio of original fill
3272 
3273   Level: developer
3274 
3275   Notes:
3276   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3277   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3278 
3279   Most users should employ the `KSP` interface for linear solvers
3280   instead of working directly with matrix algebra routines such as this.
3281   See, e.g., `KSPCreate()`.
3282 
3283   Developer Note:
3284   The Fortran interface is not autogenerated as the
3285   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3286 
3287 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3288           `MatGetOrdering()`
3289 @*/
3290 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3291 {
3292   MatFactorInfo tinfo;
3293 
3294   PetscFunctionBegin;
3295   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3296   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3297   if (info) PetscAssertPointer(info, 3);
3298   PetscValidType(mat, 1);
3299   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3300   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3301   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3302   MatCheckPreallocated(mat, 1);
3303   if (!info) {
3304     PetscCall(MatFactorInfoInitialize(&tinfo));
3305     info = &tinfo;
3306   }
3307 
3308   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3309   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3310   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3311   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3312   PetscFunctionReturn(PETSC_SUCCESS);
3313 }
3314 
3315 /*@C
3316   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3317   of a symmetric matrix.
3318 
3319   Collective
3320 
3321   Input Parameters:
3322 + fact - the factor matrix obtained with `MatGetFactor()`
3323 . mat  - the matrix
3324 . perm - row and column permutations
3325 - info - options for factorization, includes
3326 .vb
3327           fill - expected fill as ratio of original fill.
3328           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3329                    Run with the option -info to determine an optimal value to use
3330 .ve
3331 
3332   Level: developer
3333 
3334   Notes:
3335   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3336   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3337 
3338   Most users should employ the `KSP` interface for linear solvers
3339   instead of working directly with matrix algebra routines such as this.
3340   See, e.g., `KSPCreate()`.
3341 
3342   Developer Note:
3343   The Fortran interface is not autogenerated as the
3344   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3345 
3346 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3347           `MatGetOrdering()`
3348 @*/
3349 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3350 {
3351   MatFactorInfo tinfo;
3352 
3353   PetscFunctionBegin;
3354   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3355   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3356   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3357   if (info) PetscAssertPointer(info, 4);
3358   PetscValidType(fact, 1);
3359   PetscValidType(mat, 2);
3360   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3361   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3362   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3363   MatCheckPreallocated(mat, 2);
3364   if (!info) {
3365     PetscCall(MatFactorInfoInitialize(&tinfo));
3366     info = &tinfo;
3367   }
3368 
3369   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3370   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3371   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3372   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3373   PetscFunctionReturn(PETSC_SUCCESS);
3374 }
3375 
3376 /*@C
3377   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3378   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3379   `MatCholeskyFactorSymbolic()`.
3380 
3381   Collective
3382 
3383   Input Parameters:
3384 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3385 . mat  - the initial matrix that is to be factored
3386 - info - options for factorization
3387 
3388   Level: developer
3389 
3390   Note:
3391   Most users should employ the `KSP` interface for linear solvers
3392   instead of working directly with matrix algebra routines such as this.
3393   See, e.g., `KSPCreate()`.
3394 
3395   Developer Note:
3396   The Fortran interface is not autogenerated as the
3397   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3398 
3399 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3400 @*/
3401 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3402 {
3403   MatFactorInfo tinfo;
3404 
3405   PetscFunctionBegin;
3406   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3407   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3408   PetscValidType(fact, 1);
3409   PetscValidType(mat, 2);
3410   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3411   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,
3412              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3413   MatCheckPreallocated(mat, 2);
3414   if (!info) {
3415     PetscCall(MatFactorInfoInitialize(&tinfo));
3416     info = &tinfo;
3417   }
3418 
3419   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3420   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3421   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3422   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3423   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3424   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3425   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3426   PetscFunctionReturn(PETSC_SUCCESS);
3427 }
3428 
3429 /*@
3430   MatQRFactor - Performs in-place QR factorization of matrix.
3431 
3432   Collective
3433 
3434   Input Parameters:
3435 + mat  - the matrix
3436 . col  - column permutation
3437 - info - options for factorization, includes
3438 .vb
3439           fill - expected fill as ratio of original fill.
3440           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3441                    Run with the option -info to determine an optimal value to use
3442 .ve
3443 
3444   Level: developer
3445 
3446   Notes:
3447   Most users should employ the `KSP` interface for linear solvers
3448   instead of working directly with matrix algebra routines such as this.
3449   See, e.g., `KSPCreate()`.
3450 
3451   This changes the state of the matrix to a factored matrix; it cannot be used
3452   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3453 
3454   Developer Note:
3455   The Fortran interface is not autogenerated as the
3456   interface definition cannot be generated correctly [due to MatFactorInfo]
3457 
3458 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3459           `MatSetUnfactored()`
3460 @*/
3461 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3462 {
3463   PetscFunctionBegin;
3464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3465   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3466   if (info) PetscAssertPointer(info, 3);
3467   PetscValidType(mat, 1);
3468   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3469   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3470   MatCheckPreallocated(mat, 1);
3471   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3472   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3473   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3474   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3475   PetscFunctionReturn(PETSC_SUCCESS);
3476 }
3477 
3478 /*@
3479   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3480   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3481 
3482   Collective
3483 
3484   Input Parameters:
3485 + fact - the factor matrix obtained with `MatGetFactor()`
3486 . mat  - the matrix
3487 . col  - column permutation
3488 - info - options for factorization, includes
3489 .vb
3490           fill - expected fill as ratio of original fill.
3491           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3492                    Run with the option -info to determine an optimal value to use
3493 .ve
3494 
3495   Level: developer
3496 
3497   Note:
3498   Most users should employ the `KSP` interface for linear solvers
3499   instead of working directly with matrix algebra routines such as this.
3500   See, e.g., `KSPCreate()`.
3501 
3502   Developer Note:
3503   The Fortran interface is not autogenerated as the
3504   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3505 
3506 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3507 @*/
3508 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3509 {
3510   MatFactorInfo tinfo;
3511 
3512   PetscFunctionBegin;
3513   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3515   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3516   if (info) PetscAssertPointer(info, 4);
3517   PetscValidType(fact, 1);
3518   PetscValidType(mat, 2);
3519   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3520   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3521   MatCheckPreallocated(mat, 2);
3522   if (!info) {
3523     PetscCall(MatFactorInfoInitialize(&tinfo));
3524     info = &tinfo;
3525   }
3526 
3527   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3528   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3529   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3530   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3531   PetscFunctionReturn(PETSC_SUCCESS);
3532 }
3533 
3534 /*@
3535   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3536   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3537 
3538   Collective
3539 
3540   Input Parameters:
3541 + fact - the factor matrix obtained with `MatGetFactor()`
3542 . mat  - the matrix
3543 - info - options for factorization
3544 
3545   Level: developer
3546 
3547   Notes:
3548   See `MatQRFactor()` for in-place factorization.
3549 
3550   Most users should employ the `KSP` interface for linear solvers
3551   instead of working directly with matrix algebra routines such as this.
3552   See, e.g., `KSPCreate()`.
3553 
3554   Developer Note:
3555   The Fortran interface is not autogenerated as the
3556   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3557 
3558 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3559 @*/
3560 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3561 {
3562   MatFactorInfo tinfo;
3563 
3564   PetscFunctionBegin;
3565   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3567   PetscValidType(fact, 1);
3568   PetscValidType(mat, 2);
3569   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3570   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,
3571              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3572 
3573   MatCheckPreallocated(mat, 2);
3574   if (!info) {
3575     PetscCall(MatFactorInfoInitialize(&tinfo));
3576     info = &tinfo;
3577   }
3578 
3579   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3580   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3581   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3582   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3583   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3584   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3585   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3586   PetscFunctionReturn(PETSC_SUCCESS);
3587 }
3588 
3589 /*@
3590   MatSolve - Solves $A x = b$, given a factored matrix.
3591 
3592   Neighbor-wise Collective
3593 
3594   Input Parameters:
3595 + mat - the factored matrix
3596 - b   - the right-hand-side vector
3597 
3598   Output Parameter:
3599 . x - the result vector
3600 
3601   Level: developer
3602 
3603   Notes:
3604   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3605   call `MatSolve`(A,x,x).
3606 
3607   Most users should employ the `KSP` interface for linear solvers
3608   instead of working directly with matrix algebra routines such as this.
3609   See, e.g., `KSPCreate()`.
3610 
3611 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3612 @*/
3613 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3614 {
3615   PetscFunctionBegin;
3616   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3617   PetscValidType(mat, 1);
3618   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3619   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3620   PetscCheckSameComm(mat, 1, b, 2);
3621   PetscCheckSameComm(mat, 1, x, 3);
3622   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3623   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);
3624   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);
3625   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);
3626   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3627   MatCheckPreallocated(mat, 1);
3628 
3629   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3630   if (mat->factorerrortype) {
3631     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3632     PetscCall(VecSetInf(x));
3633   } else PetscUseTypeMethod(mat, solve, b, x);
3634   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3635   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3636   PetscFunctionReturn(PETSC_SUCCESS);
3637 }
3638 
3639 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3640 {
3641   Vec      b, x;
3642   PetscInt N, i;
3643   PetscErrorCode (*f)(Mat, Vec, Vec);
3644   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3645 
3646   PetscFunctionBegin;
3647   if (A->factorerrortype) {
3648     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3649     PetscCall(MatSetInf(X));
3650     PetscFunctionReturn(PETSC_SUCCESS);
3651   }
3652   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3653   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3654   PetscCall(MatBoundToCPU(A, &Abound));
3655   if (!Abound) {
3656     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3657     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3658   }
3659 #if PetscDefined(HAVE_CUDA)
3660   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3661   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3662 #elif PetscDefined(HAVE_HIP)
3663   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3664   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3665 #endif
3666   PetscCall(MatGetSize(B, NULL, &N));
3667   for (i = 0; i < N; i++) {
3668     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3669     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3670     PetscCall((*f)(A, b, x));
3671     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3672     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3673   }
3674   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3675   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3676   PetscFunctionReturn(PETSC_SUCCESS);
3677 }
3678 
3679 /*@
3680   MatMatSolve - Solves $A X = B$, given a factored matrix.
3681 
3682   Neighbor-wise Collective
3683 
3684   Input Parameters:
3685 + A - the factored matrix
3686 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3687 
3688   Output Parameter:
3689 . X - the result matrix (dense matrix)
3690 
3691   Level: developer
3692 
3693   Note:
3694   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3695   otherwise, `B` and `X` cannot be the same.
3696 
3697 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3698 @*/
3699 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3700 {
3701   PetscFunctionBegin;
3702   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3703   PetscValidType(A, 1);
3704   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3705   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3706   PetscCheckSameComm(A, 1, B, 2);
3707   PetscCheckSameComm(A, 1, X, 3);
3708   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);
3709   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);
3710   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");
3711   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3712   MatCheckPreallocated(A, 1);
3713 
3714   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3715   if (!A->ops->matsolve) {
3716     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3717     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3718   } else PetscUseTypeMethod(A, matsolve, B, X);
3719   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3720   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3721   PetscFunctionReturn(PETSC_SUCCESS);
3722 }
3723 
3724 /*@
3725   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3726 
3727   Neighbor-wise Collective
3728 
3729   Input Parameters:
3730 + A - the factored matrix
3731 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3732 
3733   Output Parameter:
3734 . X - the result matrix (dense matrix)
3735 
3736   Level: developer
3737 
3738   Note:
3739   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3740   call `MatMatSolveTranspose`(A,X,X).
3741 
3742 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3743 @*/
3744 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3745 {
3746   PetscFunctionBegin;
3747   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3748   PetscValidType(A, 1);
3749   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3750   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3751   PetscCheckSameComm(A, 1, B, 2);
3752   PetscCheckSameComm(A, 1, X, 3);
3753   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3754   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);
3755   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);
3756   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);
3757   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");
3758   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3759   MatCheckPreallocated(A, 1);
3760 
3761   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3762   if (!A->ops->matsolvetranspose) {
3763     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3764     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3765   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3766   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3767   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3768   PetscFunctionReturn(PETSC_SUCCESS);
3769 }
3770 
3771 /*@
3772   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3773 
3774   Neighbor-wise Collective
3775 
3776   Input Parameters:
3777 + A  - the factored matrix
3778 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3779 
3780   Output Parameter:
3781 . X - the result matrix (dense matrix)
3782 
3783   Level: developer
3784 
3785   Note:
3786   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
3787   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3788 
3789 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3790 @*/
3791 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3792 {
3793   PetscFunctionBegin;
3794   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3795   PetscValidType(A, 1);
3796   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3797   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3798   PetscCheckSameComm(A, 1, Bt, 2);
3799   PetscCheckSameComm(A, 1, X, 3);
3800 
3801   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3802   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);
3803   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);
3804   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");
3805   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3806   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3807   MatCheckPreallocated(A, 1);
3808 
3809   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3810   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3811   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3812   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3813   PetscFunctionReturn(PETSC_SUCCESS);
3814 }
3815 
3816 /*@
3817   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3818   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3819 
3820   Neighbor-wise Collective
3821 
3822   Input Parameters:
3823 + mat - the factored matrix
3824 - b   - the right-hand-side vector
3825 
3826   Output Parameter:
3827 . x - the result vector
3828 
3829   Level: developer
3830 
3831   Notes:
3832   `MatSolve()` should be used for most applications, as it performs
3833   a forward solve followed by a backward solve.
3834 
3835   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3836   call `MatForwardSolve`(A,x,x).
3837 
3838   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3839   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3840   `MatForwardSolve()` solves $U^T*D y = b$, and
3841   `MatBackwardSolve()` solves $U x = y$.
3842   Thus they do not provide a symmetric preconditioner.
3843 
3844 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3845 @*/
3846 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3847 {
3848   PetscFunctionBegin;
3849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3850   PetscValidType(mat, 1);
3851   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3852   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3853   PetscCheckSameComm(mat, 1, b, 2);
3854   PetscCheckSameComm(mat, 1, x, 3);
3855   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3856   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);
3857   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);
3858   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);
3859   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3860   MatCheckPreallocated(mat, 1);
3861 
3862   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3863   PetscUseTypeMethod(mat, forwardsolve, b, x);
3864   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3865   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3866   PetscFunctionReturn(PETSC_SUCCESS);
3867 }
3868 
3869 /*@
3870   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3871   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3872 
3873   Neighbor-wise Collective
3874 
3875   Input Parameters:
3876 + mat - the factored matrix
3877 - b   - the right-hand-side vector
3878 
3879   Output Parameter:
3880 . x - the result vector
3881 
3882   Level: developer
3883 
3884   Notes:
3885   `MatSolve()` should be used for most applications, as it performs
3886   a forward solve followed by a backward solve.
3887 
3888   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3889   call `MatBackwardSolve`(A,x,x).
3890 
3891   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3892   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3893   `MatForwardSolve()` solves $U^T*D y = b$, and
3894   `MatBackwardSolve()` solves $U x = y$.
3895   Thus they do not provide a symmetric preconditioner.
3896 
3897 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3898 @*/
3899 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3900 {
3901   PetscFunctionBegin;
3902   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3903   PetscValidType(mat, 1);
3904   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3905   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3906   PetscCheckSameComm(mat, 1, b, 2);
3907   PetscCheckSameComm(mat, 1, x, 3);
3908   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3909   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);
3910   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);
3911   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);
3912   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3913   MatCheckPreallocated(mat, 1);
3914 
3915   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3916   PetscUseTypeMethod(mat, backwardsolve, b, x);
3917   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3918   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3919   PetscFunctionReturn(PETSC_SUCCESS);
3920 }
3921 
3922 /*@
3923   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3924 
3925   Neighbor-wise Collective
3926 
3927   Input Parameters:
3928 + mat - the factored matrix
3929 . b   - the right-hand-side vector
3930 - y   - the vector to be added to
3931 
3932   Output Parameter:
3933 . x - the result vector
3934 
3935   Level: developer
3936 
3937   Note:
3938   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3939   call `MatSolveAdd`(A,x,y,x).
3940 
3941 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3942 @*/
3943 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3944 {
3945   PetscScalar one = 1.0;
3946   Vec         tmp;
3947 
3948   PetscFunctionBegin;
3949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3950   PetscValidType(mat, 1);
3951   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3952   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3953   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3954   PetscCheckSameComm(mat, 1, b, 2);
3955   PetscCheckSameComm(mat, 1, y, 3);
3956   PetscCheckSameComm(mat, 1, x, 4);
3957   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3958   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);
3959   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);
3960   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);
3961   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);
3962   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);
3963   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3964   MatCheckPreallocated(mat, 1);
3965 
3966   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3967   if (mat->factorerrortype) {
3968     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3969     PetscCall(VecSetInf(x));
3970   } else if (mat->ops->solveadd) {
3971     PetscUseTypeMethod(mat, solveadd, b, y, x);
3972   } else {
3973     /* do the solve then the add manually */
3974     if (x != y) {
3975       PetscCall(MatSolve(mat, b, x));
3976       PetscCall(VecAXPY(x, one, y));
3977     } else {
3978       PetscCall(VecDuplicate(x, &tmp));
3979       PetscCall(VecCopy(x, tmp));
3980       PetscCall(MatSolve(mat, b, x));
3981       PetscCall(VecAXPY(x, one, tmp));
3982       PetscCall(VecDestroy(&tmp));
3983     }
3984   }
3985   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3986   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3987   PetscFunctionReturn(PETSC_SUCCESS);
3988 }
3989 
3990 /*@
3991   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3992 
3993   Neighbor-wise Collective
3994 
3995   Input Parameters:
3996 + mat - the factored matrix
3997 - b   - the right-hand-side vector
3998 
3999   Output Parameter:
4000 . x - the result vector
4001 
4002   Level: developer
4003 
4004   Notes:
4005   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4006   call `MatSolveTranspose`(A,x,x).
4007 
4008   Most users should employ the `KSP` interface for linear solvers
4009   instead of working directly with matrix algebra routines such as this.
4010   See, e.g., `KSPCreate()`.
4011 
4012 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4013 @*/
4014 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4015 {
4016   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4017 
4018   PetscFunctionBegin;
4019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4020   PetscValidType(mat, 1);
4021   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4022   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4023   PetscCheckSameComm(mat, 1, b, 2);
4024   PetscCheckSameComm(mat, 1, x, 3);
4025   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4026   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);
4027   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);
4028   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4029   MatCheckPreallocated(mat, 1);
4030   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4031   if (mat->factorerrortype) {
4032     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4033     PetscCall(VecSetInf(x));
4034   } else {
4035     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4036     PetscCall((*f)(mat, b, x));
4037   }
4038   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4039   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4040   PetscFunctionReturn(PETSC_SUCCESS);
4041 }
4042 
4043 /*@
4044   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4045   factored matrix.
4046 
4047   Neighbor-wise Collective
4048 
4049   Input Parameters:
4050 + mat - the factored matrix
4051 . b   - the right-hand-side vector
4052 - y   - the vector to be added to
4053 
4054   Output Parameter:
4055 . x - the result vector
4056 
4057   Level: developer
4058 
4059   Note:
4060   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4061   call `MatSolveTransposeAdd`(A,x,y,x).
4062 
4063 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4064 @*/
4065 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4066 {
4067   PetscScalar one = 1.0;
4068   Vec         tmp;
4069   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4070 
4071   PetscFunctionBegin;
4072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4073   PetscValidType(mat, 1);
4074   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4075   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4076   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4077   PetscCheckSameComm(mat, 1, b, 2);
4078   PetscCheckSameComm(mat, 1, y, 3);
4079   PetscCheckSameComm(mat, 1, x, 4);
4080   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4081   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);
4082   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);
4083   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);
4084   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);
4085   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4086   MatCheckPreallocated(mat, 1);
4087 
4088   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4089   if (mat->factorerrortype) {
4090     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4091     PetscCall(VecSetInf(x));
4092   } else if (f) {
4093     PetscCall((*f)(mat, b, y, x));
4094   } else {
4095     /* do the solve then the add manually */
4096     if (x != y) {
4097       PetscCall(MatSolveTranspose(mat, b, x));
4098       PetscCall(VecAXPY(x, one, y));
4099     } else {
4100       PetscCall(VecDuplicate(x, &tmp));
4101       PetscCall(VecCopy(x, tmp));
4102       PetscCall(MatSolveTranspose(mat, b, x));
4103       PetscCall(VecAXPY(x, one, tmp));
4104       PetscCall(VecDestroy(&tmp));
4105     }
4106   }
4107   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4108   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4109   PetscFunctionReturn(PETSC_SUCCESS);
4110 }
4111 
4112 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4113 /*@
4114   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4115 
4116   Neighbor-wise Collective
4117 
4118   Input Parameters:
4119 + mat   - the matrix
4120 . b     - the right hand side
4121 . omega - the relaxation factor
4122 . flag  - flag indicating the type of SOR (see below)
4123 . shift - diagonal shift
4124 . its   - the number of iterations
4125 - lits  - the number of local iterations
4126 
4127   Output Parameter:
4128 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4129 
4130   SOR Flags:
4131 +     `SOR_FORWARD_SWEEP` - forward SOR
4132 .     `SOR_BACKWARD_SWEEP` - backward SOR
4133 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4134 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4135 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4136 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4137 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4138 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4139   upper/lower triangular part of matrix to
4140   vector (with omega)
4141 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4142 
4143   Level: developer
4144 
4145   Notes:
4146   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4147   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4148   on each processor.
4149 
4150   Application programmers will not generally use `MatSOR()` directly,
4151   but instead will employ the `KSP`/`PC` interface.
4152 
4153   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4154 
4155   Most users should employ the `KSP` interface for linear solvers
4156   instead of working directly with matrix algebra routines such as this.
4157   See, e.g., `KSPCreate()`.
4158 
4159   Vectors `x` and `b` CANNOT be the same
4160 
4161   The flags are implemented as bitwise inclusive or operations.
4162   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4163   to specify a zero initial guess for SSOR.
4164 
4165   Developer Note:
4166   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4167 
4168 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4169 @*/
4170 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4171 {
4172   PetscFunctionBegin;
4173   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4174   PetscValidType(mat, 1);
4175   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4176   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4177   PetscCheckSameComm(mat, 1, b, 2);
4178   PetscCheckSameComm(mat, 1, x, 8);
4179   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4180   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4181   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);
4182   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);
4183   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);
4184   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4185   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4186   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4187 
4188   MatCheckPreallocated(mat, 1);
4189   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4190   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4191   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4192   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4193   PetscFunctionReturn(PETSC_SUCCESS);
4194 }
4195 
4196 /*
4197       Default matrix copy routine.
4198 */
4199 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4200 {
4201   PetscInt           i, rstart = 0, rend = 0, nz;
4202   const PetscInt    *cwork;
4203   const PetscScalar *vwork;
4204 
4205   PetscFunctionBegin;
4206   if (B->assembled) PetscCall(MatZeroEntries(B));
4207   if (str == SAME_NONZERO_PATTERN) {
4208     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4209     for (i = rstart; i < rend; i++) {
4210       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4211       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4212       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4213     }
4214   } else {
4215     PetscCall(MatAYPX(B, 0.0, A, str));
4216   }
4217   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4218   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4219   PetscFunctionReturn(PETSC_SUCCESS);
4220 }
4221 
4222 /*@
4223   MatCopy - Copies a matrix to another matrix.
4224 
4225   Collective
4226 
4227   Input Parameters:
4228 + A   - the matrix
4229 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4230 
4231   Output Parameter:
4232 . B - where the copy is put
4233 
4234   Level: intermediate
4235 
4236   Notes:
4237   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4238 
4239   `MatCopy()` copies the matrix entries of a matrix to another existing
4240   matrix (after first zeroing the second matrix).  A related routine is
4241   `MatConvert()`, which first creates a new matrix and then copies the data.
4242 
4243 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4244 @*/
4245 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4246 {
4247   PetscInt i;
4248 
4249   PetscFunctionBegin;
4250   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4251   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4252   PetscValidType(A, 1);
4253   PetscValidType(B, 2);
4254   PetscCheckSameComm(A, 1, B, 2);
4255   MatCheckPreallocated(B, 2);
4256   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4257   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4258   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,
4259              A->cmap->N, B->cmap->N);
4260   MatCheckPreallocated(A, 1);
4261   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4262 
4263   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4264   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4265   else PetscCall(MatCopy_Basic(A, B, str));
4266 
4267   B->stencil.dim = A->stencil.dim;
4268   B->stencil.noc = A->stencil.noc;
4269   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4270     B->stencil.dims[i]   = A->stencil.dims[i];
4271     B->stencil.starts[i] = A->stencil.starts[i];
4272   }
4273 
4274   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4275   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4276   PetscFunctionReturn(PETSC_SUCCESS);
4277 }
4278 
4279 /*@C
4280   MatConvert - Converts a matrix to another matrix, either of the same
4281   or different type.
4282 
4283   Collective
4284 
4285   Input Parameters:
4286 + mat     - the matrix
4287 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4288    same type as the original matrix.
4289 - reuse   - denotes if the destination matrix is to be created or reused.
4290    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
4291    `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).
4292 
4293   Output Parameter:
4294 . M - pointer to place new matrix
4295 
4296   Level: intermediate
4297 
4298   Notes:
4299   `MatConvert()` first creates a new matrix and then copies the data from
4300   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4301   entries of one matrix to another already existing matrix context.
4302 
4303   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4304   the MPI communicator of the generated matrix is always the same as the communicator
4305   of the input matrix.
4306 
4307 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4308 @*/
4309 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4310 {
4311   PetscBool  sametype, issame, flg;
4312   PetscBool3 issymmetric, ishermitian;
4313   char       convname[256], mtype[256];
4314   Mat        B;
4315 
4316   PetscFunctionBegin;
4317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4318   PetscValidType(mat, 1);
4319   PetscAssertPointer(M, 4);
4320   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4321   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4322   MatCheckPreallocated(mat, 1);
4323 
4324   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4325   if (flg) newtype = mtype;
4326 
4327   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4328   PetscCall(PetscStrcmp(newtype, "same", &issame));
4329   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4330   if (reuse == MAT_REUSE_MATRIX) {
4331     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4332     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4333   }
4334 
4335   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4336     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4337     PetscFunctionReturn(PETSC_SUCCESS);
4338   }
4339 
4340   /* Cache Mat options because some converters use MatHeaderReplace  */
4341   issymmetric = mat->symmetric;
4342   ishermitian = mat->hermitian;
4343 
4344   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4345     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4346     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4347   } else {
4348     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4349     const char *prefix[3]                                 = {"seq", "mpi", ""};
4350     PetscInt    i;
4351     /*
4352        Order of precedence:
4353        0) See if newtype is a superclass of the current matrix.
4354        1) See if a specialized converter is known to the current matrix.
4355        2) See if a specialized converter is known to the desired matrix class.
4356        3) See if a good general converter is registered for the desired class
4357           (as of 6/27/03 only MATMPIADJ falls into this category).
4358        4) See if a good general converter is known for the current matrix.
4359        5) Use a really basic converter.
4360     */
4361 
4362     /* 0) See if newtype is a superclass of the current matrix.
4363           i.e mat is mpiaij and newtype is aij */
4364     for (i = 0; i < 2; i++) {
4365       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4367       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4368       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4369       if (flg) {
4370         if (reuse == MAT_INPLACE_MATRIX) {
4371           PetscCall(PetscInfo(mat, "Early return\n"));
4372           PetscFunctionReturn(PETSC_SUCCESS);
4373         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4374           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4375           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4376           PetscFunctionReturn(PETSC_SUCCESS);
4377         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4378           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4379           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4380           PetscFunctionReturn(PETSC_SUCCESS);
4381         }
4382       }
4383     }
4384     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4385     for (i = 0; i < 3; i++) {
4386       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4387       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4388       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4390       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4392       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4393       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4394       if (conv) goto foundconv;
4395     }
4396 
4397     /* 2)  See if a specialized converter is known to the desired matrix class. */
4398     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4399     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4400     PetscCall(MatSetType(B, newtype));
4401     for (i = 0; i < 3; i++) {
4402       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4403       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4404       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4405       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4406       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4407       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4408       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4409       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4410       if (conv) {
4411         PetscCall(MatDestroy(&B));
4412         goto foundconv;
4413       }
4414     }
4415 
4416     /* 3) See if a good general converter is registered for the desired class */
4417     conv = B->ops->convertfrom;
4418     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4419     PetscCall(MatDestroy(&B));
4420     if (conv) goto foundconv;
4421 
4422     /* 4) See if a good general converter is known for the current matrix */
4423     if (mat->ops->convert) conv = mat->ops->convert;
4424     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4425     if (conv) goto foundconv;
4426 
4427     /* 5) Use a really basic converter. */
4428     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4429     conv = MatConvert_Basic;
4430 
4431   foundconv:
4432     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4433     PetscCall((*conv)(mat, newtype, reuse, M));
4434     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4435       /* the block sizes must be same if the mappings are copied over */
4436       (*M)->rmap->bs = mat->rmap->bs;
4437       (*M)->cmap->bs = mat->cmap->bs;
4438       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4439       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4440       (*M)->rmap->mapping = mat->rmap->mapping;
4441       (*M)->cmap->mapping = mat->cmap->mapping;
4442     }
4443     (*M)->stencil.dim = mat->stencil.dim;
4444     (*M)->stencil.noc = mat->stencil.noc;
4445     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4446       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4447       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4448     }
4449     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4450   }
4451   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4452 
4453   /* Copy Mat options */
4454   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4455   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4456   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4457   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4458   PetscFunctionReturn(PETSC_SUCCESS);
4459 }
4460 
4461 /*@C
4462   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4463 
4464   Not Collective
4465 
4466   Input Parameter:
4467 . mat - the matrix, must be a factored matrix
4468 
4469   Output Parameter:
4470 . type - the string name of the package (do not free this string)
4471 
4472   Level: intermediate
4473 
4474   Fortran Note:
4475   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4476 
4477 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4478 @*/
4479 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4480 {
4481   PetscErrorCode (*conv)(Mat, MatSolverType *);
4482 
4483   PetscFunctionBegin;
4484   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4485   PetscValidType(mat, 1);
4486   PetscAssertPointer(type, 2);
4487   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4488   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4489   if (conv) PetscCall((*conv)(mat, type));
4490   else *type = MATSOLVERPETSC;
4491   PetscFunctionReturn(PETSC_SUCCESS);
4492 }
4493 
4494 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4495 struct _MatSolverTypeForSpecifcType {
4496   MatType mtype;
4497   /* no entry for MAT_FACTOR_NONE */
4498   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4499   MatSolverTypeForSpecifcType next;
4500 };
4501 
4502 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4503 struct _MatSolverTypeHolder {
4504   char                       *name;
4505   MatSolverTypeForSpecifcType handlers;
4506   MatSolverTypeHolder         next;
4507 };
4508 
4509 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4510 
4511 /*@C
4512   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4513 
4514   Input Parameters:
4515 + package      - name of the package, for example petsc or superlu
4516 . mtype        - the matrix type that works with this package
4517 . ftype        - the type of factorization supported by the package
4518 - createfactor - routine that will create the factored matrix ready to be used
4519 
4520   Level: developer
4521 
4522 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4523   `MatGetFactor()`
4524 @*/
4525 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4526 {
4527   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4528   PetscBool                   flg;
4529   MatSolverTypeForSpecifcType inext, iprev = NULL;
4530 
4531   PetscFunctionBegin;
4532   PetscCall(MatInitializePackage());
4533   if (!next) {
4534     PetscCall(PetscNew(&MatSolverTypeHolders));
4535     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4536     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4537     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4538     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4539     PetscFunctionReturn(PETSC_SUCCESS);
4540   }
4541   while (next) {
4542     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4543     if (flg) {
4544       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4545       inext = next->handlers;
4546       while (inext) {
4547         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4548         if (flg) {
4549           inext->createfactor[(int)ftype - 1] = createfactor;
4550           PetscFunctionReturn(PETSC_SUCCESS);
4551         }
4552         iprev = inext;
4553         inext = inext->next;
4554       }
4555       PetscCall(PetscNew(&iprev->next));
4556       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4557       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4558       PetscFunctionReturn(PETSC_SUCCESS);
4559     }
4560     prev = next;
4561     next = next->next;
4562   }
4563   PetscCall(PetscNew(&prev->next));
4564   PetscCall(PetscStrallocpy(package, &prev->next->name));
4565   PetscCall(PetscNew(&prev->next->handlers));
4566   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4567   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4568   PetscFunctionReturn(PETSC_SUCCESS);
4569 }
4570 
4571 /*@C
4572   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4573 
4574   Input Parameters:
4575 + 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
4576 . ftype - the type of factorization supported by the type
4577 - mtype - the matrix type that works with this type
4578 
4579   Output Parameters:
4580 + foundtype    - `PETSC_TRUE` if the type was registered
4581 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4582 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4583 
4584   Calling sequence of `createfactor`:
4585 + A     - the matrix providing the factor matrix
4586 . mtype - the `MatType` of the factor requested
4587 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4588 
4589   Level: developer
4590 
4591   Note:
4592   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4593   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4594   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4595 
4596 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4597           `MatInitializePackage()`
4598 @*/
4599 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4600 {
4601   MatSolverTypeHolder         next = MatSolverTypeHolders;
4602   PetscBool                   flg;
4603   MatSolverTypeForSpecifcType inext;
4604 
4605   PetscFunctionBegin;
4606   if (foundtype) *foundtype = PETSC_FALSE;
4607   if (foundmtype) *foundmtype = PETSC_FALSE;
4608   if (createfactor) *createfactor = NULL;
4609 
4610   if (type) {
4611     while (next) {
4612       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4613       if (flg) {
4614         if (foundtype) *foundtype = PETSC_TRUE;
4615         inext = next->handlers;
4616         while (inext) {
4617           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4618           if (flg) {
4619             if (foundmtype) *foundmtype = PETSC_TRUE;
4620             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4621             PetscFunctionReturn(PETSC_SUCCESS);
4622           }
4623           inext = inext->next;
4624         }
4625       }
4626       next = next->next;
4627     }
4628   } else {
4629     while (next) {
4630       inext = next->handlers;
4631       while (inext) {
4632         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4633         if (flg && inext->createfactor[(int)ftype - 1]) {
4634           if (foundtype) *foundtype = PETSC_TRUE;
4635           if (foundmtype) *foundmtype = PETSC_TRUE;
4636           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4637           PetscFunctionReturn(PETSC_SUCCESS);
4638         }
4639         inext = inext->next;
4640       }
4641       next = next->next;
4642     }
4643     /* try with base classes inext->mtype */
4644     next = MatSolverTypeHolders;
4645     while (next) {
4646       inext = next->handlers;
4647       while (inext) {
4648         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4649         if (flg && inext->createfactor[(int)ftype - 1]) {
4650           if (foundtype) *foundtype = PETSC_TRUE;
4651           if (foundmtype) *foundmtype = PETSC_TRUE;
4652           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4653           PetscFunctionReturn(PETSC_SUCCESS);
4654         }
4655         inext = inext->next;
4656       }
4657       next = next->next;
4658     }
4659   }
4660   PetscFunctionReturn(PETSC_SUCCESS);
4661 }
4662 
4663 PetscErrorCode MatSolverTypeDestroy(void)
4664 {
4665   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4666   MatSolverTypeForSpecifcType inext, iprev;
4667 
4668   PetscFunctionBegin;
4669   while (next) {
4670     PetscCall(PetscFree(next->name));
4671     inext = next->handlers;
4672     while (inext) {
4673       PetscCall(PetscFree(inext->mtype));
4674       iprev = inext;
4675       inext = inext->next;
4676       PetscCall(PetscFree(iprev));
4677     }
4678     prev = next;
4679     next = next->next;
4680     PetscCall(PetscFree(prev));
4681   }
4682   MatSolverTypeHolders = NULL;
4683   PetscFunctionReturn(PETSC_SUCCESS);
4684 }
4685 
4686 /*@C
4687   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4688 
4689   Logically Collective
4690 
4691   Input Parameter:
4692 . mat - the matrix
4693 
4694   Output Parameter:
4695 . flg - `PETSC_TRUE` if uses the ordering
4696 
4697   Level: developer
4698 
4699   Note:
4700   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4701   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4702 
4703 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4704 @*/
4705 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4706 {
4707   PetscFunctionBegin;
4708   *flg = mat->canuseordering;
4709   PetscFunctionReturn(PETSC_SUCCESS);
4710 }
4711 
4712 /*@C
4713   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4714 
4715   Logically Collective
4716 
4717   Input Parameters:
4718 + mat   - the matrix obtained with `MatGetFactor()`
4719 - ftype - the factorization type to be used
4720 
4721   Output Parameter:
4722 . otype - the preferred ordering type
4723 
4724   Level: developer
4725 
4726 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4727 @*/
4728 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4729 {
4730   PetscFunctionBegin;
4731   *otype = mat->preferredordering[ftype];
4732   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4733   PetscFunctionReturn(PETSC_SUCCESS);
4734 }
4735 
4736 /*@C
4737   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4738 
4739   Collective
4740 
4741   Input Parameters:
4742 + mat   - the matrix
4743 . 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
4744           the other criteria is returned
4745 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4746 
4747   Output Parameter:
4748 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4749 
4750   Options Database Keys:
4751 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4752 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4753                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4754 
4755   Level: intermediate
4756 
4757   Notes:
4758   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4759   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4760 
4761   Users usually access the factorization solvers via `KSP`
4762 
4763   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4764   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
4765 
4766   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4767   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4768   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4769 
4770   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4771   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4772   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4773 
4774   Developer Note:
4775   This should actually be called `MatCreateFactor()` since it creates a new factor object
4776 
4777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4778           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4779           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4780 @*/
4781 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4782 {
4783   PetscBool foundtype, foundmtype;
4784   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4785 
4786   PetscFunctionBegin;
4787   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4788   PetscValidType(mat, 1);
4789 
4790   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4791   MatCheckPreallocated(mat, 1);
4792 
4793   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4794   if (!foundtype) {
4795     if (type) {
4796       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],
4797               ((PetscObject)mat)->type_name, type);
4798     } else {
4799       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);
4800     }
4801   }
4802   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4803   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);
4804 
4805   PetscCall((*conv)(mat, ftype, f));
4806   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4807   PetscFunctionReturn(PETSC_SUCCESS);
4808 }
4809 
4810 /*@C
4811   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4812 
4813   Not Collective
4814 
4815   Input Parameters:
4816 + mat   - the matrix
4817 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4818 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4819 
4820   Output Parameter:
4821 . flg - PETSC_TRUE if the factorization is available
4822 
4823   Level: intermediate
4824 
4825   Notes:
4826   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4827   such as pastix, superlu, mumps etc.
4828 
4829   PETSc must have been ./configure to use the external solver, using the option --download-package
4830 
4831   Developer Note:
4832   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4833 
4834 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4835           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4836 @*/
4837 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4838 {
4839   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4840 
4841   PetscFunctionBegin;
4842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4843   PetscAssertPointer(flg, 4);
4844 
4845   *flg = PETSC_FALSE;
4846   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4847 
4848   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4849   MatCheckPreallocated(mat, 1);
4850 
4851   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4852   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4853   PetscFunctionReturn(PETSC_SUCCESS);
4854 }
4855 
4856 /*@
4857   MatDuplicate - Duplicates a matrix including the non-zero structure.
4858 
4859   Collective
4860 
4861   Input Parameters:
4862 + mat - the matrix
4863 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4864         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4865 
4866   Output Parameter:
4867 . M - pointer to place new matrix
4868 
4869   Level: intermediate
4870 
4871   Notes:
4872   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4873 
4874   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4875 
4876   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.
4877 
4878   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4879   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4880   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4881 
4882 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4883 @*/
4884 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4885 {
4886   Mat         B;
4887   VecType     vtype;
4888   PetscInt    i;
4889   PetscObject dm, container_h, container_d;
4890   void (*viewf)(void);
4891 
4892   PetscFunctionBegin;
4893   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4894   PetscValidType(mat, 1);
4895   PetscAssertPointer(M, 3);
4896   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4897   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4898   MatCheckPreallocated(mat, 1);
4899 
4900   *M = NULL;
4901   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4902   PetscUseTypeMethod(mat, duplicate, op, M);
4903   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4904   B = *M;
4905 
4906   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4907   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4908   PetscCall(MatGetVecType(mat, &vtype));
4909   PetscCall(MatSetVecType(B, vtype));
4910 
4911   B->stencil.dim = mat->stencil.dim;
4912   B->stencil.noc = mat->stencil.noc;
4913   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4914     B->stencil.dims[i]   = mat->stencil.dims[i];
4915     B->stencil.starts[i] = mat->stencil.starts[i];
4916   }
4917 
4918   B->nooffproczerorows = mat->nooffproczerorows;
4919   B->nooffprocentries  = mat->nooffprocentries;
4920 
4921   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4922   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4923   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4924   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4925   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4926   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4927   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4928   PetscFunctionReturn(PETSC_SUCCESS);
4929 }
4930 
4931 /*@
4932   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4933 
4934   Logically Collective
4935 
4936   Input Parameter:
4937 . mat - the matrix
4938 
4939   Output Parameter:
4940 . v - the diagonal of the matrix
4941 
4942   Level: intermediate
4943 
4944   Note:
4945   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4946   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4947   is larger than `ndiag`, the values of the remaining entries are unspecified.
4948 
4949   Currently only correct in parallel for square matrices.
4950 
4951 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4952 @*/
4953 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4954 {
4955   PetscFunctionBegin;
4956   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4957   PetscValidType(mat, 1);
4958   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4959   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4960   MatCheckPreallocated(mat, 1);
4961   if (PetscDefined(USE_DEBUG)) {
4962     PetscInt nv, row, col, ndiag;
4963 
4964     PetscCall(VecGetLocalSize(v, &nv));
4965     PetscCall(MatGetLocalSize(mat, &row, &col));
4966     ndiag = PetscMin(row, col);
4967     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);
4968   }
4969 
4970   PetscUseTypeMethod(mat, getdiagonal, v);
4971   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4972   PetscFunctionReturn(PETSC_SUCCESS);
4973 }
4974 
4975 /*@C
4976   MatGetRowMin - Gets the minimum value (of the real part) of each
4977   row of the matrix
4978 
4979   Logically Collective
4980 
4981   Input Parameter:
4982 . mat - the matrix
4983 
4984   Output Parameters:
4985 + v   - the vector for storing the maximums
4986 - idx - the indices of the column found for each row (optional)
4987 
4988   Level: intermediate
4989 
4990   Note:
4991   The result of this call are the same as if one converted the matrix to dense format
4992   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4993 
4994   This code is only implemented for a couple of matrix formats.
4995 
4996 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4997           `MatGetRowMax()`
4998 @*/
4999 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5000 {
5001   PetscFunctionBegin;
5002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5003   PetscValidType(mat, 1);
5004   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5005   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5006 
5007   if (!mat->cmap->N) {
5008     PetscCall(VecSet(v, PETSC_MAX_REAL));
5009     if (idx) {
5010       PetscInt i, m = mat->rmap->n;
5011       for (i = 0; i < m; i++) idx[i] = -1;
5012     }
5013   } else {
5014     MatCheckPreallocated(mat, 1);
5015   }
5016   PetscUseTypeMethod(mat, getrowmin, v, idx);
5017   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5018   PetscFunctionReturn(PETSC_SUCCESS);
5019 }
5020 
5021 /*@C
5022   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5023   row of the matrix
5024 
5025   Logically Collective
5026 
5027   Input Parameter:
5028 . mat - the matrix
5029 
5030   Output Parameters:
5031 + v   - the vector for storing the minimums
5032 - idx - the indices of the column found for each row (or `NULL` if not needed)
5033 
5034   Level: intermediate
5035 
5036   Notes:
5037   if a row is completely empty or has only 0.0 values then the `idx` value for that
5038   row is 0 (the first column).
5039 
5040   This code is only implemented for a couple of matrix formats.
5041 
5042 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5043 @*/
5044 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5045 {
5046   PetscFunctionBegin;
5047   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5048   PetscValidType(mat, 1);
5049   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5050   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5051   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5052 
5053   if (!mat->cmap->N) {
5054     PetscCall(VecSet(v, 0.0));
5055     if (idx) {
5056       PetscInt i, m = mat->rmap->n;
5057       for (i = 0; i < m; i++) idx[i] = -1;
5058     }
5059   } else {
5060     MatCheckPreallocated(mat, 1);
5061     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5062     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5063   }
5064   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5065   PetscFunctionReturn(PETSC_SUCCESS);
5066 }
5067 
5068 /*@C
5069   MatGetRowMax - Gets the maximum value (of the real part) of each
5070   row of the matrix
5071 
5072   Logically Collective
5073 
5074   Input Parameter:
5075 . mat - the matrix
5076 
5077   Output Parameters:
5078 + v   - the vector for storing the maximums
5079 - idx - the indices of the column found for each row (optional)
5080 
5081   Level: intermediate
5082 
5083   Notes:
5084   The result of this call are the same as if one converted the matrix to dense format
5085   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5086 
5087   This code is only implemented for a couple of matrix formats.
5088 
5089 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5090 @*/
5091 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5092 {
5093   PetscFunctionBegin;
5094   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5095   PetscValidType(mat, 1);
5096   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5098 
5099   if (!mat->cmap->N) {
5100     PetscCall(VecSet(v, PETSC_MIN_REAL));
5101     if (idx) {
5102       PetscInt i, m = mat->rmap->n;
5103       for (i = 0; i < m; i++) idx[i] = -1;
5104     }
5105   } else {
5106     MatCheckPreallocated(mat, 1);
5107     PetscUseTypeMethod(mat, getrowmax, v, idx);
5108   }
5109   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5110   PetscFunctionReturn(PETSC_SUCCESS);
5111 }
5112 
5113 /*@C
5114   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5115   row of the matrix
5116 
5117   Logically Collective
5118 
5119   Input Parameter:
5120 . mat - the matrix
5121 
5122   Output Parameters:
5123 + v   - the vector for storing the maximums
5124 - idx - the indices of the column found for each row (or `NULL` if not needed)
5125 
5126   Level: intermediate
5127 
5128   Notes:
5129   if a row is completely empty or has only 0.0 values then the `idx` value for that
5130   row is 0 (the first column).
5131 
5132   This code is only implemented for a couple of matrix formats.
5133 
5134 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5135 @*/
5136 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5137 {
5138   PetscFunctionBegin;
5139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5140   PetscValidType(mat, 1);
5141   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5142   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5143 
5144   if (!mat->cmap->N) {
5145     PetscCall(VecSet(v, 0.0));
5146     if (idx) {
5147       PetscInt i, m = mat->rmap->n;
5148       for (i = 0; i < m; i++) idx[i] = -1;
5149     }
5150   } else {
5151     MatCheckPreallocated(mat, 1);
5152     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5153     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5154   }
5155   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5156   PetscFunctionReturn(PETSC_SUCCESS);
5157 }
5158 
5159 /*@C
5160   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5161 
5162   Logically Collective
5163 
5164   Input Parameter:
5165 . mat - the matrix
5166 
5167   Output Parameter:
5168 . v - the vector for storing the sum
5169 
5170   Level: intermediate
5171 
5172   This code is only implemented for a couple of matrix formats.
5173 
5174 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5175 @*/
5176 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5177 {
5178   PetscFunctionBegin;
5179   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5180   PetscValidType(mat, 1);
5181   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5182   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5183 
5184   if (!mat->cmap->N) {
5185     PetscCall(VecSet(v, 0.0));
5186   } else {
5187     MatCheckPreallocated(mat, 1);
5188     PetscUseTypeMethod(mat, getrowsumabs, v);
5189   }
5190   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5191   PetscFunctionReturn(PETSC_SUCCESS);
5192 }
5193 
5194 /*@
5195   MatGetRowSum - Gets the sum of each row of the matrix
5196 
5197   Logically or Neighborhood Collective
5198 
5199   Input Parameter:
5200 . mat - the matrix
5201 
5202   Output Parameter:
5203 . v - the vector for storing the sum of rows
5204 
5205   Level: intermediate
5206 
5207   Note:
5208   This code is slow since it is not currently specialized for different formats
5209 
5210 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5211 @*/
5212 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5213 {
5214   Vec ones;
5215 
5216   PetscFunctionBegin;
5217   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5218   PetscValidType(mat, 1);
5219   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5220   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5221   MatCheckPreallocated(mat, 1);
5222   PetscCall(MatCreateVecs(mat, &ones, NULL));
5223   PetscCall(VecSet(ones, 1.));
5224   PetscCall(MatMult(mat, ones, v));
5225   PetscCall(VecDestroy(&ones));
5226   PetscFunctionReturn(PETSC_SUCCESS);
5227 }
5228 
5229 /*@
5230   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5231   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5232 
5233   Collective
5234 
5235   Input Parameter:
5236 . mat - the matrix to provide the transpose
5237 
5238   Output Parameter:
5239 . 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
5240 
5241   Level: advanced
5242 
5243   Note:
5244   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
5245   routine allows bypassing that call.
5246 
5247 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5248 @*/
5249 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5250 {
5251   PetscContainer  rB = NULL;
5252   MatParentState *rb = NULL;
5253 
5254   PetscFunctionBegin;
5255   PetscCall(PetscNew(&rb));
5256   rb->id    = ((PetscObject)mat)->id;
5257   rb->state = 0;
5258   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5259   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5260   PetscCall(PetscContainerSetPointer(rB, rb));
5261   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5262   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5263   PetscCall(PetscObjectDereference((PetscObject)rB));
5264   PetscFunctionReturn(PETSC_SUCCESS);
5265 }
5266 
5267 /*@
5268   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5269 
5270   Collective
5271 
5272   Input Parameters:
5273 + mat   - the matrix to transpose
5274 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5275 
5276   Output Parameter:
5277 . B - the transpose
5278 
5279   Level: intermediate
5280 
5281   Notes:
5282   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5283 
5284   `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5285   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5286 
5287   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.
5288 
5289   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5290 
5291   If mat is unchanged from the last call this function returns immediately without recomputing the result
5292 
5293   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5294 
5295 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5296           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5297 @*/
5298 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5299 {
5300   PetscContainer  rB = NULL;
5301   MatParentState *rb = NULL;
5302 
5303   PetscFunctionBegin;
5304   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5305   PetscValidType(mat, 1);
5306   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5307   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5308   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5309   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5310   MatCheckPreallocated(mat, 1);
5311   if (reuse == MAT_REUSE_MATRIX) {
5312     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5313     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5314     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5315     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5316     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5317   }
5318 
5319   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5320   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5321     PetscUseTypeMethod(mat, transpose, reuse, B);
5322     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5323   }
5324   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5325 
5326   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5327   if (reuse != MAT_INPLACE_MATRIX) {
5328     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5329     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5330     rb->state        = ((PetscObject)mat)->state;
5331     rb->nonzerostate = mat->nonzerostate;
5332   }
5333   PetscFunctionReturn(PETSC_SUCCESS);
5334 }
5335 
5336 /*@
5337   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5338 
5339   Collective
5340 
5341   Input Parameter:
5342 . A - the matrix to transpose
5343 
5344   Output Parameter:
5345 . 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
5346       numerical portion.
5347 
5348   Level: intermediate
5349 
5350   Note:
5351   This is not supported for many matrix types, use `MatTranspose()` in those cases
5352 
5353 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5354 @*/
5355 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5356 {
5357   PetscFunctionBegin;
5358   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5359   PetscValidType(A, 1);
5360   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5361   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5362   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5363   PetscUseTypeMethod(A, transposesymbolic, B);
5364   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5365 
5366   PetscCall(MatTransposeSetPrecursor(A, *B));
5367   PetscFunctionReturn(PETSC_SUCCESS);
5368 }
5369 
5370 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5371 {
5372   PetscContainer  rB;
5373   MatParentState *rb;
5374 
5375   PetscFunctionBegin;
5376   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5377   PetscValidType(A, 1);
5378   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5379   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5380   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5381   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5382   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5383   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5384   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5385   PetscFunctionReturn(PETSC_SUCCESS);
5386 }
5387 
5388 /*@
5389   MatIsTranspose - Test whether a matrix is another one's transpose,
5390   or its own, in which case it tests symmetry.
5391 
5392   Collective
5393 
5394   Input Parameters:
5395 + A   - the matrix to test
5396 . B   - the matrix to test against, this can equal the first parameter
5397 - tol - tolerance, differences between entries smaller than this are counted as zero
5398 
5399   Output Parameter:
5400 . flg - the result
5401 
5402   Level: intermediate
5403 
5404   Notes:
5405   Only available for `MATAIJ` matrices.
5406 
5407   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5408   test involves parallel copies of the block off-diagonal parts of the matrix.
5409 
5410 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5411 @*/
5412 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5413 {
5414   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5415 
5416   PetscFunctionBegin;
5417   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5418   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5419   PetscAssertPointer(flg, 4);
5420   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5421   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5422   *flg = PETSC_FALSE;
5423   if (f && g) {
5424     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5425     PetscCall((*f)(A, B, tol, flg));
5426   } else {
5427     MatType mattype;
5428 
5429     PetscCall(MatGetType(f ? B : A, &mattype));
5430     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5431   }
5432   PetscFunctionReturn(PETSC_SUCCESS);
5433 }
5434 
5435 /*@
5436   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5437 
5438   Collective
5439 
5440   Input Parameters:
5441 + mat   - the matrix to transpose and complex conjugate
5442 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5443 
5444   Output Parameter:
5445 . B - the Hermitian transpose
5446 
5447   Level: intermediate
5448 
5449 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5450 @*/
5451 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5452 {
5453   PetscFunctionBegin;
5454   PetscCall(MatTranspose(mat, reuse, B));
5455 #if defined(PETSC_USE_COMPLEX)
5456   PetscCall(MatConjugate(*B));
5457 #endif
5458   PetscFunctionReturn(PETSC_SUCCESS);
5459 }
5460 
5461 /*@
5462   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5463 
5464   Collective
5465 
5466   Input Parameters:
5467 + A   - the matrix to test
5468 . B   - the matrix to test against, this can equal the first parameter
5469 - tol - tolerance, differences between entries smaller than this are counted as zero
5470 
5471   Output Parameter:
5472 . flg - the result
5473 
5474   Level: intermediate
5475 
5476   Notes:
5477   Only available for `MATAIJ` matrices.
5478 
5479   The sequential algorithm
5480   has a running time of the order of the number of nonzeros; the parallel
5481   test involves parallel copies of the block off-diagonal parts of the matrix.
5482 
5483 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5484 @*/
5485 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5486 {
5487   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5488 
5489   PetscFunctionBegin;
5490   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5491   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5492   PetscAssertPointer(flg, 4);
5493   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5494   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5495   if (f && g) {
5496     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5497     PetscCall((*f)(A, B, tol, flg));
5498   }
5499   PetscFunctionReturn(PETSC_SUCCESS);
5500 }
5501 
5502 /*@
5503   MatPermute - Creates a new matrix with rows and columns permuted from the
5504   original.
5505 
5506   Collective
5507 
5508   Input Parameters:
5509 + mat - the matrix to permute
5510 . row - row permutation, each processor supplies only the permutation for its rows
5511 - col - column permutation, each processor supplies only the permutation for its columns
5512 
5513   Output Parameter:
5514 . B - the permuted matrix
5515 
5516   Level: advanced
5517 
5518   Note:
5519   The index sets map from row/col of permuted matrix to row/col of original matrix.
5520   The index sets should be on the same communicator as mat and have the same local sizes.
5521 
5522   Developer Note:
5523   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5524   exploit the fact that row and col are permutations, consider implementing the
5525   more general `MatCreateSubMatrix()` instead.
5526 
5527 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5528 @*/
5529 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5530 {
5531   PetscFunctionBegin;
5532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5533   PetscValidType(mat, 1);
5534   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5535   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5536   PetscAssertPointer(B, 4);
5537   PetscCheckSameComm(mat, 1, row, 2);
5538   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5539   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5540   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5541   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5542   MatCheckPreallocated(mat, 1);
5543 
5544   if (mat->ops->permute) {
5545     PetscUseTypeMethod(mat, permute, row, col, B);
5546     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5547   } else {
5548     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5549   }
5550   PetscFunctionReturn(PETSC_SUCCESS);
5551 }
5552 
5553 /*@
5554   MatEqual - Compares two matrices.
5555 
5556   Collective
5557 
5558   Input Parameters:
5559 + A - the first matrix
5560 - B - the second matrix
5561 
5562   Output Parameter:
5563 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5564 
5565   Level: intermediate
5566 
5567 .seealso: [](ch_matrices), `Mat`
5568 @*/
5569 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5570 {
5571   PetscFunctionBegin;
5572   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5573   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5574   PetscValidType(A, 1);
5575   PetscValidType(B, 2);
5576   PetscAssertPointer(flg, 3);
5577   PetscCheckSameComm(A, 1, B, 2);
5578   MatCheckPreallocated(A, 1);
5579   MatCheckPreallocated(B, 2);
5580   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5581   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5582   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,
5583              B->cmap->N);
5584   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5585     PetscUseTypeMethod(A, equal, B, flg);
5586   } else {
5587     PetscCall(MatMultEqual(A, B, 10, flg));
5588   }
5589   PetscFunctionReturn(PETSC_SUCCESS);
5590 }
5591 
5592 /*@
5593   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5594   matrices that are stored as vectors.  Either of the two scaling
5595   matrices can be `NULL`.
5596 
5597   Collective
5598 
5599   Input Parameters:
5600 + mat - the matrix to be scaled
5601 . l   - the left scaling vector (or `NULL`)
5602 - r   - the right scaling vector (or `NULL`)
5603 
5604   Level: intermediate
5605 
5606   Note:
5607   `MatDiagonalScale()` computes $A = LAR$, where
5608   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5609   The L scales the rows of the matrix, the R scales the columns of the matrix.
5610 
5611 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5612 @*/
5613 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5614 {
5615   PetscFunctionBegin;
5616   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5617   PetscValidType(mat, 1);
5618   if (l) {
5619     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5620     PetscCheckSameComm(mat, 1, l, 2);
5621   }
5622   if (r) {
5623     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5624     PetscCheckSameComm(mat, 1, r, 3);
5625   }
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   MatCheckPreallocated(mat, 1);
5629   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5630 
5631   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5632   PetscUseTypeMethod(mat, diagonalscale, l, r);
5633   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5634   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5635   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5636   PetscFunctionReturn(PETSC_SUCCESS);
5637 }
5638 
5639 /*@
5640   MatScale - Scales all elements of a matrix by a given number.
5641 
5642   Logically Collective
5643 
5644   Input Parameters:
5645 + mat - the matrix to be scaled
5646 - a   - the scaling value
5647 
5648   Level: intermediate
5649 
5650 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5651 @*/
5652 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5653 {
5654   PetscFunctionBegin;
5655   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5656   PetscValidType(mat, 1);
5657   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5658   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5659   PetscValidLogicalCollectiveScalar(mat, a, 2);
5660   MatCheckPreallocated(mat, 1);
5661 
5662   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5663   if (a != (PetscScalar)1.0) {
5664     PetscUseTypeMethod(mat, scale, a);
5665     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5666   }
5667   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5668   PetscFunctionReturn(PETSC_SUCCESS);
5669 }
5670 
5671 /*@
5672   MatNorm - Calculates various norms of a matrix.
5673 
5674   Collective
5675 
5676   Input Parameters:
5677 + mat  - the matrix
5678 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5679 
5680   Output Parameter:
5681 . nrm - the resulting norm
5682 
5683   Level: intermediate
5684 
5685 .seealso: [](ch_matrices), `Mat`
5686 @*/
5687 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5688 {
5689   PetscFunctionBegin;
5690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5691   PetscValidType(mat, 1);
5692   PetscAssertPointer(nrm, 3);
5693 
5694   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5695   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5696   MatCheckPreallocated(mat, 1);
5697 
5698   PetscUseTypeMethod(mat, norm, type, nrm);
5699   PetscFunctionReturn(PETSC_SUCCESS);
5700 }
5701 
5702 /*
5703      This variable is used to prevent counting of MatAssemblyBegin() that
5704    are called from within a MatAssemblyEnd().
5705 */
5706 static PetscInt MatAssemblyEnd_InUse = 0;
5707 /*@
5708   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5709   be called after completing all calls to `MatSetValues()`.
5710 
5711   Collective
5712 
5713   Input Parameters:
5714 + mat  - the matrix
5715 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5716 
5717   Level: beginner
5718 
5719   Notes:
5720   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5721   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5722 
5723   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5724   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5725   using the matrix.
5726 
5727   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5728   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
5729   a global collective operation requiring all processes that share the matrix.
5730 
5731   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5732   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5733   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5734 
5735 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5736 @*/
5737 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5738 {
5739   PetscFunctionBegin;
5740   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5741   PetscValidType(mat, 1);
5742   MatCheckPreallocated(mat, 1);
5743   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5744   if (mat->assembled) {
5745     mat->was_assembled = PETSC_TRUE;
5746     mat->assembled     = PETSC_FALSE;
5747   }
5748 
5749   if (!MatAssemblyEnd_InUse) {
5750     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5751     PetscTryTypeMethod(mat, assemblybegin, type);
5752     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5753   } else PetscTryTypeMethod(mat, assemblybegin, type);
5754   PetscFunctionReturn(PETSC_SUCCESS);
5755 }
5756 
5757 /*@
5758   MatAssembled - Indicates if a matrix has been assembled and is ready for
5759   use; for example, in matrix-vector product.
5760 
5761   Not Collective
5762 
5763   Input Parameter:
5764 . mat - the matrix
5765 
5766   Output Parameter:
5767 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5768 
5769   Level: advanced
5770 
5771 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5772 @*/
5773 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5774 {
5775   PetscFunctionBegin;
5776   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5777   PetscAssertPointer(assembled, 2);
5778   *assembled = mat->assembled;
5779   PetscFunctionReturn(PETSC_SUCCESS);
5780 }
5781 
5782 /*@
5783   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5784   be called after `MatAssemblyBegin()`.
5785 
5786   Collective
5787 
5788   Input Parameters:
5789 + mat  - the matrix
5790 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5791 
5792   Options Database Keys:
5793 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5794 . -mat_view ::ascii_info_detail      - Prints more detailed info
5795 . -mat_view                          - Prints matrix in ASCII format
5796 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5797 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5798 . -display <name>                    - Sets display name (default is host)
5799 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5800 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5801 . -viewer_socket_machine <machine>   - Machine to use for socket
5802 . -viewer_socket_port <port>         - Port number to use for socket
5803 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5804 
5805   Level: beginner
5806 
5807 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5808 @*/
5809 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5810 {
5811   static PetscInt inassm = 0;
5812   PetscBool       flg    = PETSC_FALSE;
5813 
5814   PetscFunctionBegin;
5815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5816   PetscValidType(mat, 1);
5817 
5818   inassm++;
5819   MatAssemblyEnd_InUse++;
5820   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5821     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5822     PetscTryTypeMethod(mat, assemblyend, type);
5823     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5824   } else PetscTryTypeMethod(mat, assemblyend, type);
5825 
5826   /* Flush assembly is not a true assembly */
5827   if (type != MAT_FLUSH_ASSEMBLY) {
5828     if (mat->num_ass) {
5829       if (!mat->symmetry_eternal) {
5830         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5831         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5832       }
5833       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5834       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5835     }
5836     mat->num_ass++;
5837     mat->assembled        = PETSC_TRUE;
5838     mat->ass_nonzerostate = mat->nonzerostate;
5839   }
5840 
5841   mat->insertmode = NOT_SET_VALUES;
5842   MatAssemblyEnd_InUse--;
5843   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5844   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5845     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5846 
5847     if (mat->checksymmetryonassembly) {
5848       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5849       if (flg) {
5850         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5851       } else {
5852         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5853       }
5854     }
5855     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5856   }
5857   inassm--;
5858   PetscFunctionReturn(PETSC_SUCCESS);
5859 }
5860 
5861 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5862 /*@
5863   MatSetOption - Sets a parameter option for a matrix. Some options
5864   may be specific to certain storage formats.  Some options
5865   determine how values will be inserted (or added). Sorted,
5866   row-oriented input will generally assemble the fastest. The default
5867   is row-oriented.
5868 
5869   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5870 
5871   Input Parameters:
5872 + mat - the matrix
5873 . op  - the option, one of those listed below (and possibly others),
5874 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5875 
5876   Options Describing Matrix Structure:
5877 + `MAT_SPD`                         - symmetric positive definite
5878 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5879 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5880 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5881 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5882 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5883 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5884 
5885    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5886    do not need to be computed (usually at a high cost)
5887 
5888    Options For Use with `MatSetValues()`:
5889    Insert a logically dense subblock, which can be
5890 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5891 
5892    These options reflect the data you pass in with `MatSetValues()`; it has
5893    nothing to do with how the data is stored internally in the matrix
5894    data structure.
5895 
5896    When (re)assembling a matrix, we can restrict the input for
5897    efficiency/debugging purposes.  These options include
5898 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5899 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5900 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5901 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5902 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5903 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5904         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5905         performance for very large process counts.
5906 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5907         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5908         functions, instead sending only neighbor messages.
5909 
5910   Level: intermediate
5911 
5912   Notes:
5913   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5914 
5915   Some options are relevant only for particular matrix types and
5916   are thus ignored by others.  Other options are not supported by
5917   certain matrix types and will generate an error message if set.
5918 
5919   If using Fortran to compute a matrix, one may need to
5920   use the column-oriented option (or convert to the row-oriented
5921   format).
5922 
5923   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5924   that would generate a new entry in the nonzero structure is instead
5925   ignored.  Thus, if memory has not already been allocated for this particular
5926   data, then the insertion is ignored. For dense matrices, in which
5927   the entire array is allocated, no entries are ever ignored.
5928   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5929 
5930   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5931   that would generate a new entry in the nonzero structure instead produces
5932   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
5933 
5934   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5935   that would generate a new entry that has not been preallocated will
5936   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5937   only.) This is a useful flag when debugging matrix memory preallocation.
5938   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5939 
5940   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5941   other processors should be dropped, rather than stashed.
5942   This is useful if you know that the "owning" processor is also
5943   always generating the correct matrix entries, so that PETSc need
5944   not transfer duplicate entries generated on another processor.
5945 
5946   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5947   searches during matrix assembly. When this flag is set, the hash table
5948   is created during the first matrix assembly. This hash table is
5949   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5950   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5951   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5952   supported by `MATMPIBAIJ` format only.
5953 
5954   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5955   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
5956 
5957   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5958   a zero location in the matrix
5959 
5960   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5961 
5962   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5963   zero row routines and thus improves performance for very large process counts.
5964 
5965   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5966   part of the matrix (since they should match the upper triangular part).
5967 
5968   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5969   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
5970   with finite difference schemes with non-periodic boundary conditions.
5971 
5972   Developer Note:
5973   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5974   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5975   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5976   not changed.
5977 
5978 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5979 @*/
5980 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5981 {
5982   PetscFunctionBegin;
5983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5984   if (op > 0) {
5985     PetscValidLogicalCollectiveEnum(mat, op, 2);
5986     PetscValidLogicalCollectiveBool(mat, flg, 3);
5987   }
5988 
5989   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);
5990 
5991   switch (op) {
5992   case MAT_FORCE_DIAGONAL_ENTRIES:
5993     mat->force_diagonals = flg;
5994     PetscFunctionReturn(PETSC_SUCCESS);
5995   case MAT_NO_OFF_PROC_ENTRIES:
5996     mat->nooffprocentries = flg;
5997     PetscFunctionReturn(PETSC_SUCCESS);
5998   case MAT_SUBSET_OFF_PROC_ENTRIES:
5999     mat->assembly_subset = flg;
6000     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6001 #if !defined(PETSC_HAVE_MPIUNI)
6002       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6003 #endif
6004       mat->stash.first_assembly_done = PETSC_FALSE;
6005     }
6006     PetscFunctionReturn(PETSC_SUCCESS);
6007   case MAT_NO_OFF_PROC_ZERO_ROWS:
6008     mat->nooffproczerorows = flg;
6009     PetscFunctionReturn(PETSC_SUCCESS);
6010   case MAT_SPD:
6011     if (flg) {
6012       mat->spd                    = PETSC_BOOL3_TRUE;
6013       mat->symmetric              = PETSC_BOOL3_TRUE;
6014       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6015     } else {
6016       mat->spd = PETSC_BOOL3_FALSE;
6017     }
6018     break;
6019   case MAT_SYMMETRIC:
6020     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6021     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6022 #if !defined(PETSC_USE_COMPLEX)
6023     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6024 #endif
6025     break;
6026   case MAT_HERMITIAN:
6027     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6028     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6029 #if !defined(PETSC_USE_COMPLEX)
6030     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6031 #endif
6032     break;
6033   case MAT_STRUCTURALLY_SYMMETRIC:
6034     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6035     break;
6036   case MAT_SYMMETRY_ETERNAL:
6037     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");
6038     mat->symmetry_eternal = flg;
6039     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6040     break;
6041   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6042     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");
6043     mat->structural_symmetry_eternal = flg;
6044     break;
6045   case MAT_SPD_ETERNAL:
6046     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");
6047     mat->spd_eternal = flg;
6048     if (flg) {
6049       mat->structural_symmetry_eternal = PETSC_TRUE;
6050       mat->symmetry_eternal            = PETSC_TRUE;
6051     }
6052     break;
6053   case MAT_STRUCTURE_ONLY:
6054     mat->structure_only = flg;
6055     break;
6056   case MAT_SORTED_FULL:
6057     mat->sortedfull = flg;
6058     break;
6059   default:
6060     break;
6061   }
6062   PetscTryTypeMethod(mat, setoption, op, flg);
6063   PetscFunctionReturn(PETSC_SUCCESS);
6064 }
6065 
6066 /*@
6067   MatGetOption - Gets a parameter option that has been set for a matrix.
6068 
6069   Logically Collective
6070 
6071   Input Parameters:
6072 + mat - the matrix
6073 - op  - the option, this only responds to certain options, check the code for which ones
6074 
6075   Output Parameter:
6076 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6077 
6078   Level: intermediate
6079 
6080   Notes:
6081   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6082 
6083   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6084   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6085 
6086 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6087     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6088 @*/
6089 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6090 {
6091   PetscFunctionBegin;
6092   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6093   PetscValidType(mat, 1);
6094 
6095   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);
6096   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()");
6097 
6098   switch (op) {
6099   case MAT_NO_OFF_PROC_ENTRIES:
6100     *flg = mat->nooffprocentries;
6101     break;
6102   case MAT_NO_OFF_PROC_ZERO_ROWS:
6103     *flg = mat->nooffproczerorows;
6104     break;
6105   case MAT_SYMMETRIC:
6106     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6107     break;
6108   case MAT_HERMITIAN:
6109     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6110     break;
6111   case MAT_STRUCTURALLY_SYMMETRIC:
6112     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6113     break;
6114   case MAT_SPD:
6115     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6116     break;
6117   case MAT_SYMMETRY_ETERNAL:
6118     *flg = mat->symmetry_eternal;
6119     break;
6120   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6121     *flg = mat->symmetry_eternal;
6122     break;
6123   default:
6124     break;
6125   }
6126   PetscFunctionReturn(PETSC_SUCCESS);
6127 }
6128 
6129 /*@
6130   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6131   this routine retains the old nonzero structure.
6132 
6133   Logically Collective
6134 
6135   Input Parameter:
6136 . mat - the matrix
6137 
6138   Level: intermediate
6139 
6140   Note:
6141   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.
6142   See the Performance chapter of the users manual for information on preallocating matrices.
6143 
6144 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6145 @*/
6146 PetscErrorCode MatZeroEntries(Mat mat)
6147 {
6148   PetscFunctionBegin;
6149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6150   PetscValidType(mat, 1);
6151   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6152   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");
6153   MatCheckPreallocated(mat, 1);
6154 
6155   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6156   PetscUseTypeMethod(mat, zeroentries);
6157   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6158   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6159   PetscFunctionReturn(PETSC_SUCCESS);
6160 }
6161 
6162 /*@
6163   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6164   of a set of rows and columns of a matrix.
6165 
6166   Collective
6167 
6168   Input Parameters:
6169 + mat     - the matrix
6170 . numRows - the number of rows/columns to zero
6171 . rows    - the global row indices
6172 . diag    - value put in the diagonal of the eliminated rows
6173 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6174 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6175 
6176   Level: intermediate
6177 
6178   Notes:
6179   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6180 
6181   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6182   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
6183 
6184   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6185   Krylov method to take advantage of the known solution on the zeroed rows.
6186 
6187   For the parallel case, all processes that share the matrix (i.e.,
6188   those in the communicator used for matrix creation) MUST call this
6189   routine, regardless of whether any rows being zeroed are owned by
6190   them.
6191 
6192   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6193   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
6194   missing.
6195 
6196   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6197   list only rows local to itself).
6198 
6199   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6200 
6201 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6202           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6203 @*/
6204 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6205 {
6206   PetscFunctionBegin;
6207   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6208   PetscValidType(mat, 1);
6209   if (numRows) PetscAssertPointer(rows, 3);
6210   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6211   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6212   MatCheckPreallocated(mat, 1);
6213 
6214   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6215   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6216   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6217   PetscFunctionReturn(PETSC_SUCCESS);
6218 }
6219 
6220 /*@
6221   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6222   of a set of rows and columns of a matrix.
6223 
6224   Collective
6225 
6226   Input Parameters:
6227 + mat  - the matrix
6228 . is   - the rows to zero
6229 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6230 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6231 - b    - optional vector of right hand side, that will be adjusted by provided solution
6232 
6233   Level: intermediate
6234 
6235   Note:
6236   See `MatZeroRowsColumns()` for details on how this routine operates.
6237 
6238 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6239           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6240 @*/
6241 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6242 {
6243   PetscInt        numRows;
6244   const PetscInt *rows;
6245 
6246   PetscFunctionBegin;
6247   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6248   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6249   PetscValidType(mat, 1);
6250   PetscValidType(is, 2);
6251   PetscCall(ISGetLocalSize(is, &numRows));
6252   PetscCall(ISGetIndices(is, &rows));
6253   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6254   PetscCall(ISRestoreIndices(is, &rows));
6255   PetscFunctionReturn(PETSC_SUCCESS);
6256 }
6257 
6258 /*@
6259   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6260   of a set of rows of a matrix.
6261 
6262   Collective
6263 
6264   Input Parameters:
6265 + mat     - the matrix
6266 . numRows - the number of rows to zero
6267 . rows    - the global row indices
6268 . diag    - value put in the diagonal of the zeroed rows
6269 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6270 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6271 
6272   Level: intermediate
6273 
6274   Notes:
6275   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6276 
6277   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6278 
6279   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6280   Krylov method to take advantage of the known solution on the zeroed rows.
6281 
6282   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)
6283   from the matrix.
6284 
6285   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6286   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6287   formats this does not alter the nonzero structure.
6288 
6289   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6290   of the matrix is not changed the values are
6291   merely zeroed.
6292 
6293   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6294   formats can optionally remove the main diagonal entry from the
6295   nonzero structure as well, by passing 0.0 as the final argument).
6296 
6297   For the parallel case, all processes that share the matrix (i.e.,
6298   those in the communicator used for matrix creation) MUST call this
6299   routine, regardless of whether any rows being zeroed are owned by
6300   them.
6301 
6302   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6303   list only rows local to itself).
6304 
6305   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6306   owns that are to be zeroed. This saves a global synchronization in the implementation.
6307 
6308 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6309           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6310 @*/
6311 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6312 {
6313   PetscFunctionBegin;
6314   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6315   PetscValidType(mat, 1);
6316   if (numRows) PetscAssertPointer(rows, 3);
6317   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6318   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6319   MatCheckPreallocated(mat, 1);
6320 
6321   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6322   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6323   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6324   PetscFunctionReturn(PETSC_SUCCESS);
6325 }
6326 
6327 /*@
6328   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6329   of a set of rows of a matrix.
6330 
6331   Collective
6332 
6333   Input Parameters:
6334 + mat  - the matrix
6335 . is   - index set of rows to remove (if `NULL` then no row is removed)
6336 . diag - value put in all diagonals of eliminated rows
6337 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6338 - b    - optional vector of right hand side, that will be adjusted by provided solution
6339 
6340   Level: intermediate
6341 
6342   Note:
6343   See `MatZeroRows()` for details on how this routine operates.
6344 
6345 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6346           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6347 @*/
6348 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6349 {
6350   PetscInt        numRows = 0;
6351   const PetscInt *rows    = NULL;
6352 
6353   PetscFunctionBegin;
6354   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6355   PetscValidType(mat, 1);
6356   if (is) {
6357     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6358     PetscCall(ISGetLocalSize(is, &numRows));
6359     PetscCall(ISGetIndices(is, &rows));
6360   }
6361   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6362   if (is) PetscCall(ISRestoreIndices(is, &rows));
6363   PetscFunctionReturn(PETSC_SUCCESS);
6364 }
6365 
6366 /*@
6367   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6368   of a set of rows of a matrix. These rows must be local to the process.
6369 
6370   Collective
6371 
6372   Input Parameters:
6373 + mat     - the matrix
6374 . numRows - the number of rows to remove
6375 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6376 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6377 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6378 - b       - optional vector of right hand side, that will be adjusted by provided solution
6379 
6380   Level: intermediate
6381 
6382   Notes:
6383   See `MatZeroRows()` for details on how this routine operates.
6384 
6385   The grid coordinates are across the entire grid, not just the local portion
6386 
6387   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6388   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6389   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6390   `DM_BOUNDARY_PERIODIC` boundary type.
6391 
6392   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
6393   a single value per point) you can skip filling those indices.
6394 
6395   Fortran Note:
6396   `idxm` and `idxn` should be declared as
6397 $     MatStencil idxm(4, m)
6398   and the values inserted using
6399 .vb
6400     idxm(MatStencil_i, 1) = i
6401     idxm(MatStencil_j, 1) = j
6402     idxm(MatStencil_k, 1) = k
6403     idxm(MatStencil_c, 1) = c
6404    etc
6405 .ve
6406 
6407 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6408           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6409 @*/
6410 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6411 {
6412   PetscInt  dim    = mat->stencil.dim;
6413   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6414   PetscInt *dims   = mat->stencil.dims + 1;
6415   PetscInt *starts = mat->stencil.starts;
6416   PetscInt *dxm    = (PetscInt *)rows;
6417   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6418 
6419   PetscFunctionBegin;
6420   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6421   PetscValidType(mat, 1);
6422   if (numRows) PetscAssertPointer(rows, 3);
6423 
6424   PetscCall(PetscMalloc1(numRows, &jdxm));
6425   for (i = 0; i < numRows; ++i) {
6426     /* Skip unused dimensions (they are ordered k, j, i, c) */
6427     for (j = 0; j < 3 - sdim; ++j) dxm++;
6428     /* Local index in X dir */
6429     tmp = *dxm++ - starts[0];
6430     /* Loop over remaining dimensions */
6431     for (j = 0; j < dim - 1; ++j) {
6432       /* If nonlocal, set index to be negative */
6433       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6434       /* Update local index */
6435       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6436     }
6437     /* Skip component slot if necessary */
6438     if (mat->stencil.noc) dxm++;
6439     /* Local row number */
6440     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6441   }
6442   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6443   PetscCall(PetscFree(jdxm));
6444   PetscFunctionReturn(PETSC_SUCCESS);
6445 }
6446 
6447 /*@
6448   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6449   of a set of rows and columns of a matrix.
6450 
6451   Collective
6452 
6453   Input Parameters:
6454 + mat     - the matrix
6455 . numRows - the number of rows/columns to remove
6456 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6457 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6458 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6459 - b       - optional vector of right hand side, that will be adjusted by provided solution
6460 
6461   Level: intermediate
6462 
6463   Notes:
6464   See `MatZeroRowsColumns()` for details on how this routine operates.
6465 
6466   The grid coordinates are across the entire grid, not just the local portion
6467 
6468   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6469   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6470   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6471   `DM_BOUNDARY_PERIODIC` boundary type.
6472 
6473   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
6474   a single value per point) you can skip filling those indices.
6475 
6476   Fortran Note:
6477   `idxm` and `idxn` should be declared as
6478 $     MatStencil idxm(4, m)
6479   and the values inserted using
6480 .vb
6481     idxm(MatStencil_i, 1) = i
6482     idxm(MatStencil_j, 1) = j
6483     idxm(MatStencil_k, 1) = k
6484     idxm(MatStencil_c, 1) = c
6485     etc
6486 .ve
6487 
6488 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6489           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6490 @*/
6491 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6492 {
6493   PetscInt  dim    = mat->stencil.dim;
6494   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6495   PetscInt *dims   = mat->stencil.dims + 1;
6496   PetscInt *starts = mat->stencil.starts;
6497   PetscInt *dxm    = (PetscInt *)rows;
6498   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6499 
6500   PetscFunctionBegin;
6501   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6502   PetscValidType(mat, 1);
6503   if (numRows) PetscAssertPointer(rows, 3);
6504 
6505   PetscCall(PetscMalloc1(numRows, &jdxm));
6506   for (i = 0; i < numRows; ++i) {
6507     /* Skip unused dimensions (they are ordered k, j, i, c) */
6508     for (j = 0; j < 3 - sdim; ++j) dxm++;
6509     /* Local index in X dir */
6510     tmp = *dxm++ - starts[0];
6511     /* Loop over remaining dimensions */
6512     for (j = 0; j < dim - 1; ++j) {
6513       /* If nonlocal, set index to be negative */
6514       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6515       /* Update local index */
6516       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6517     }
6518     /* Skip component slot if necessary */
6519     if (mat->stencil.noc) dxm++;
6520     /* Local row number */
6521     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6522   }
6523   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6524   PetscCall(PetscFree(jdxm));
6525   PetscFunctionReturn(PETSC_SUCCESS);
6526 }
6527 
6528 /*@C
6529   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6530   of a set of rows of a matrix; using local numbering of rows.
6531 
6532   Collective
6533 
6534   Input Parameters:
6535 + mat     - the matrix
6536 . numRows - the number of rows to remove
6537 . rows    - the local row indices
6538 . diag    - value put in all diagonals of eliminated rows
6539 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6540 - b       - optional vector of right hand side, that will be adjusted by provided solution
6541 
6542   Level: intermediate
6543 
6544   Notes:
6545   Before calling `MatZeroRowsLocal()`, the user must first set the
6546   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6547 
6548   See `MatZeroRows()` for details on how this routine operates.
6549 
6550 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6551           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6552 @*/
6553 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6554 {
6555   PetscFunctionBegin;
6556   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6557   PetscValidType(mat, 1);
6558   if (numRows) PetscAssertPointer(rows, 3);
6559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6561   MatCheckPreallocated(mat, 1);
6562 
6563   if (mat->ops->zerorowslocal) {
6564     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6565   } else {
6566     IS              is, newis;
6567     const PetscInt *newRows;
6568 
6569     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6570     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6571     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6572     PetscCall(ISGetIndices(newis, &newRows));
6573     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6574     PetscCall(ISRestoreIndices(newis, &newRows));
6575     PetscCall(ISDestroy(&newis));
6576     PetscCall(ISDestroy(&is));
6577   }
6578   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6579   PetscFunctionReturn(PETSC_SUCCESS);
6580 }
6581 
6582 /*@
6583   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6584   of a set of rows of a matrix; using local numbering of rows.
6585 
6586   Collective
6587 
6588   Input Parameters:
6589 + mat  - the matrix
6590 . is   - index set of rows to remove
6591 . diag - value put in all diagonals of eliminated rows
6592 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6593 - b    - optional vector of right hand side, that will be adjusted by provided solution
6594 
6595   Level: intermediate
6596 
6597   Notes:
6598   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6599   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6600 
6601   See `MatZeroRows()` for details on how this routine operates.
6602 
6603 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6604           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6605 @*/
6606 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6607 {
6608   PetscInt        numRows;
6609   const PetscInt *rows;
6610 
6611   PetscFunctionBegin;
6612   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6613   PetscValidType(mat, 1);
6614   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6615   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6616   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6617   MatCheckPreallocated(mat, 1);
6618 
6619   PetscCall(ISGetLocalSize(is, &numRows));
6620   PetscCall(ISGetIndices(is, &rows));
6621   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6622   PetscCall(ISRestoreIndices(is, &rows));
6623   PetscFunctionReturn(PETSC_SUCCESS);
6624 }
6625 
6626 /*@
6627   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6628   of a set of rows and columns of a matrix; using local numbering of rows.
6629 
6630   Collective
6631 
6632   Input Parameters:
6633 + mat     - the matrix
6634 . numRows - the number of rows to remove
6635 . rows    - the global row indices
6636 . diag    - value put in all diagonals of eliminated rows
6637 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6638 - b       - optional vector of right hand side, that will be adjusted by provided solution
6639 
6640   Level: intermediate
6641 
6642   Notes:
6643   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6644   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6645 
6646   See `MatZeroRowsColumns()` for details on how this routine operates.
6647 
6648 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6649           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6650 @*/
6651 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6652 {
6653   IS              is, newis;
6654   const PetscInt *newRows;
6655 
6656   PetscFunctionBegin;
6657   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6658   PetscValidType(mat, 1);
6659   if (numRows) PetscAssertPointer(rows, 3);
6660   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6661   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6662   MatCheckPreallocated(mat, 1);
6663 
6664   PetscCheck(mat->cmap->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_COPY_VALUES, &is));
6666   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6667   PetscCall(ISGetIndices(newis, &newRows));
6668   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6669   PetscCall(ISRestoreIndices(newis, &newRows));
6670   PetscCall(ISDestroy(&newis));
6671   PetscCall(ISDestroy(&is));
6672   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6673   PetscFunctionReturn(PETSC_SUCCESS);
6674 }
6675 
6676 /*@
6677   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6678   of a set of rows and columns of a matrix; using local numbering of rows.
6679 
6680   Collective
6681 
6682   Input Parameters:
6683 + mat  - the matrix
6684 . is   - index set of rows to remove
6685 . diag - value put in all diagonals of eliminated rows
6686 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6687 - b    - optional vector of right hand side, that will be adjusted by provided solution
6688 
6689   Level: intermediate
6690 
6691   Notes:
6692   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6693   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6694 
6695   See `MatZeroRowsColumns()` for details on how this routine operates.
6696 
6697 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6698           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6699 @*/
6700 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6701 {
6702   PetscInt        numRows;
6703   const PetscInt *rows;
6704 
6705   PetscFunctionBegin;
6706   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6707   PetscValidType(mat, 1);
6708   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6709   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6710   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6711   MatCheckPreallocated(mat, 1);
6712 
6713   PetscCall(ISGetLocalSize(is, &numRows));
6714   PetscCall(ISGetIndices(is, &rows));
6715   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6716   PetscCall(ISRestoreIndices(is, &rows));
6717   PetscFunctionReturn(PETSC_SUCCESS);
6718 }
6719 
6720 /*@C
6721   MatGetSize - Returns the numbers of rows and columns in a matrix.
6722 
6723   Not Collective
6724 
6725   Input Parameter:
6726 . mat - the matrix
6727 
6728   Output Parameters:
6729 + m - the number of global rows
6730 - n - the number of global columns
6731 
6732   Level: beginner
6733 
6734   Note:
6735   Both output parameters can be `NULL` on input.
6736 
6737 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6738 @*/
6739 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6740 {
6741   PetscFunctionBegin;
6742   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6743   if (m) *m = mat->rmap->N;
6744   if (n) *n = mat->cmap->N;
6745   PetscFunctionReturn(PETSC_SUCCESS);
6746 }
6747 
6748 /*@C
6749   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6750   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6751 
6752   Not Collective
6753 
6754   Input Parameter:
6755 . mat - the matrix
6756 
6757   Output Parameters:
6758 + m - the number of local rows, use `NULL` to not obtain this value
6759 - n - the number of local columns, use `NULL` to not obtain this value
6760 
6761   Level: beginner
6762 
6763 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6764 @*/
6765 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6766 {
6767   PetscFunctionBegin;
6768   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6769   if (m) PetscAssertPointer(m, 2);
6770   if (n) PetscAssertPointer(n, 3);
6771   if (m) *m = mat->rmap->n;
6772   if (n) *n = mat->cmap->n;
6773   PetscFunctionReturn(PETSC_SUCCESS);
6774 }
6775 
6776 /*@C
6777   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6778   vector one multiplies this matrix by that are owned by this processor.
6779 
6780   Not Collective, unless matrix has not been allocated, then collective
6781 
6782   Input Parameter:
6783 . mat - the matrix
6784 
6785   Output Parameters:
6786 + m - the global index of the first local column, use `NULL` to not obtain this value
6787 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6788 
6789   Level: developer
6790 
6791   Note:
6792   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6793   Layouts](sec_matlayout) for details on matrix layouts.
6794 
6795 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6796 @*/
6797 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6798 {
6799   PetscFunctionBegin;
6800   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6801   PetscValidType(mat, 1);
6802   if (m) PetscAssertPointer(m, 2);
6803   if (n) PetscAssertPointer(n, 3);
6804   MatCheckPreallocated(mat, 1);
6805   if (m) *m = mat->cmap->rstart;
6806   if (n) *n = mat->cmap->rend;
6807   PetscFunctionReturn(PETSC_SUCCESS);
6808 }
6809 
6810 /*@C
6811   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6812   this MPI process.
6813 
6814   Not Collective
6815 
6816   Input Parameter:
6817 . mat - the matrix
6818 
6819   Output Parameters:
6820 + m - the global index of the first local row, use `NULL` to not obtain this value
6821 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6822 
6823   Level: beginner
6824 
6825   Note:
6826   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6827   would contain the result of a matrix vector product with this matrix. See [Matrix
6828   Layouts](sec_matlayout) for details on matrix layouts.
6829 
6830 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6831           `PetscLayout`
6832 @*/
6833 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6834 {
6835   PetscFunctionBegin;
6836   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6837   PetscValidType(mat, 1);
6838   if (m) PetscAssertPointer(m, 2);
6839   if (n) PetscAssertPointer(n, 3);
6840   MatCheckPreallocated(mat, 1);
6841   if (m) *m = mat->rmap->rstart;
6842   if (n) *n = mat->rmap->rend;
6843   PetscFunctionReturn(PETSC_SUCCESS);
6844 }
6845 
6846 /*@C
6847   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6848   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6849 
6850   Not Collective, unless matrix has not been allocated
6851 
6852   Input Parameter:
6853 . mat - the matrix
6854 
6855   Output Parameter:
6856 . ranges - start of each processors portion plus one more than the total length at the end
6857 
6858   Level: beginner
6859 
6860   Note:
6861   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6862   would contain the result of a matrix vector product with this matrix. See [Matrix
6863   Layouts](sec_matlayout) for details on matrix layouts.
6864 
6865 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6866 @*/
6867 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6868 {
6869   PetscFunctionBegin;
6870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6871   PetscValidType(mat, 1);
6872   MatCheckPreallocated(mat, 1);
6873   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6874   PetscFunctionReturn(PETSC_SUCCESS);
6875 }
6876 
6877 /*@C
6878   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6879   vector one multiplies this vector by that are owned by each processor.
6880 
6881   Not Collective, unless matrix has not been allocated
6882 
6883   Input Parameter:
6884 . mat - the matrix
6885 
6886   Output Parameter:
6887 . ranges - start of each processors portion plus one more than the total length at the end
6888 
6889   Level: beginner
6890 
6891   Note:
6892   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6893   Layouts](sec_matlayout) for details on matrix layouts.
6894 
6895 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6896 @*/
6897 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6898 {
6899   PetscFunctionBegin;
6900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6901   PetscValidType(mat, 1);
6902   MatCheckPreallocated(mat, 1);
6903   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6904   PetscFunctionReturn(PETSC_SUCCESS);
6905 }
6906 
6907 /*@C
6908   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6909 
6910   Not Collective
6911 
6912   Input Parameter:
6913 . A - matrix
6914 
6915   Output Parameters:
6916 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6917 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6918 
6919   Level: intermediate
6920 
6921   Note:
6922   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6923   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6924   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6925   details on matrix layouts.
6926 
6927 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6928 @*/
6929 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6930 {
6931   PetscErrorCode (*f)(Mat, IS *, IS *);
6932 
6933   PetscFunctionBegin;
6934   MatCheckPreallocated(A, 1);
6935   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6936   if (f) {
6937     PetscCall((*f)(A, rows, cols));
6938   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6939     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6940     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6941   }
6942   PetscFunctionReturn(PETSC_SUCCESS);
6943 }
6944 
6945 /*@C
6946   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6947   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6948   to complete the factorization.
6949 
6950   Collective
6951 
6952   Input Parameters:
6953 + fact - the factorized matrix obtained with `MatGetFactor()`
6954 . mat  - the matrix
6955 . row  - row permutation
6956 . col  - column permutation
6957 - info - structure containing
6958 .vb
6959       levels - number of levels of fill.
6960       expected fill - as ratio of original fill.
6961       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6962                 missing diagonal entries)
6963 .ve
6964 
6965   Level: developer
6966 
6967   Notes:
6968   See [Matrix Factorization](sec_matfactor) for additional information.
6969 
6970   Most users should employ the `KSP` interface for linear solvers
6971   instead of working directly with matrix algebra routines such as this.
6972   See, e.g., `KSPCreate()`.
6973 
6974   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
6975 
6976   Developer Note:
6977   The Fortran interface is not autogenerated as the
6978   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6979 
6980 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6981           `MatGetOrdering()`, `MatFactorInfo`
6982 @*/
6983 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6984 {
6985   PetscFunctionBegin;
6986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6987   PetscValidType(mat, 2);
6988   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6989   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6990   PetscAssertPointer(info, 5);
6991   PetscAssertPointer(fact, 1);
6992   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6993   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6994   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6995   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6996   MatCheckPreallocated(mat, 2);
6997 
6998   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6999   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7000   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7001   PetscFunctionReturn(PETSC_SUCCESS);
7002 }
7003 
7004 /*@C
7005   MatICCFactorSymbolic - Performs symbolic incomplete
7006   Cholesky factorization for a symmetric matrix.  Use
7007   `MatCholeskyFactorNumeric()` to complete the factorization.
7008 
7009   Collective
7010 
7011   Input Parameters:
7012 + fact - the factorized matrix obtained with `MatGetFactor()`
7013 . mat  - the matrix to be factored
7014 . perm - row and column permutation
7015 - info - structure containing
7016 .vb
7017       levels - number of levels of fill.
7018       expected fill - as ratio of original fill.
7019 .ve
7020 
7021   Level: developer
7022 
7023   Notes:
7024   Most users should employ the `KSP` interface for linear solvers
7025   instead of working directly with matrix algebra routines such as this.
7026   See, e.g., `KSPCreate()`.
7027 
7028   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7029 
7030   Developer Note:
7031   The Fortran interface is not autogenerated as the
7032   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7033 
7034 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7035 @*/
7036 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7037 {
7038   PetscFunctionBegin;
7039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7040   PetscValidType(mat, 2);
7041   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7042   PetscAssertPointer(info, 4);
7043   PetscAssertPointer(fact, 1);
7044   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7045   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7046   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7047   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7048   MatCheckPreallocated(mat, 2);
7049 
7050   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7051   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7052   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7053   PetscFunctionReturn(PETSC_SUCCESS);
7054 }
7055 
7056 /*@C
7057   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7058   points to an array of valid matrices, they may be reused to store the new
7059   submatrices.
7060 
7061   Collective
7062 
7063   Input Parameters:
7064 + mat   - the matrix
7065 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7066 . irow  - index set of rows to extract
7067 . icol  - index set of columns to extract
7068 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7069 
7070   Output Parameter:
7071 . submat - the array of submatrices
7072 
7073   Level: advanced
7074 
7075   Notes:
7076   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7077   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7078   to extract a parallel submatrix.
7079 
7080   Some matrix types place restrictions on the row and column
7081   indices, such as that they be sorted or that they be equal to each other.
7082 
7083   The index sets may not have duplicate entries.
7084 
7085   When extracting submatrices from a parallel matrix, each processor can
7086   form a different submatrix by setting the rows and columns of its
7087   individual index sets according to the local submatrix desired.
7088 
7089   When finished using the submatrices, the user should destroy
7090   them with `MatDestroySubMatrices()`.
7091 
7092   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7093   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7094 
7095   This routine creates the matrices in submat; you should NOT create them before
7096   calling it. It also allocates the array of matrix pointers submat.
7097 
7098   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7099   request one row/column in a block, they must request all rows/columns that are in
7100   that block. For example, if the block size is 2 you cannot request just row 0 and
7101   column 0.
7102 
7103   Fortran Note:
7104   The Fortran interface is slightly different from that given below; it
7105   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7106 
7107 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7108 @*/
7109 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7110 {
7111   PetscInt  i;
7112   PetscBool eq;
7113 
7114   PetscFunctionBegin;
7115   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7116   PetscValidType(mat, 1);
7117   if (n) {
7118     PetscAssertPointer(irow, 3);
7119     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7120     PetscAssertPointer(icol, 4);
7121     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7122   }
7123   PetscAssertPointer(submat, 6);
7124   if (n && scall == MAT_REUSE_MATRIX) {
7125     PetscAssertPointer(*submat, 6);
7126     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7127   }
7128   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7129   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7130   MatCheckPreallocated(mat, 1);
7131   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7132   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7133   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7134   for (i = 0; i < n; i++) {
7135     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7136     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7137     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7138 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7139     if (mat->boundtocpu && mat->bindingpropagates) {
7140       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7141       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7142     }
7143 #endif
7144   }
7145   PetscFunctionReturn(PETSC_SUCCESS);
7146 }
7147 
7148 /*@C
7149   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7150 
7151   Collective
7152 
7153   Input Parameters:
7154 + mat   - the matrix
7155 . n     - the number of submatrixes to be extracted
7156 . irow  - index set of rows to extract
7157 . icol  - index set of columns to extract
7158 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7159 
7160   Output Parameter:
7161 . submat - the array of submatrices
7162 
7163   Level: advanced
7164 
7165   Note:
7166   This is used by `PCGASM`
7167 
7168 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7169 @*/
7170 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7171 {
7172   PetscInt  i;
7173   PetscBool eq;
7174 
7175   PetscFunctionBegin;
7176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7177   PetscValidType(mat, 1);
7178   if (n) {
7179     PetscAssertPointer(irow, 3);
7180     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7181     PetscAssertPointer(icol, 4);
7182     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7183   }
7184   PetscAssertPointer(submat, 6);
7185   if (n && scall == MAT_REUSE_MATRIX) {
7186     PetscAssertPointer(*submat, 6);
7187     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7188   }
7189   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7190   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7191   MatCheckPreallocated(mat, 1);
7192 
7193   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7194   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7195   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7196   for (i = 0; i < n; i++) {
7197     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7198     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7199   }
7200   PetscFunctionReturn(PETSC_SUCCESS);
7201 }
7202 
7203 /*@C
7204   MatDestroyMatrices - Destroys an array of matrices.
7205 
7206   Collective
7207 
7208   Input Parameters:
7209 + n   - the number of local matrices
7210 - mat - the matrices (this is a pointer to the array of matrices)
7211 
7212   Level: advanced
7213 
7214   Note:
7215   Frees not only the matrices, but also the array that contains the matrices
7216 
7217   Fortran Note:
7218   This does not free the array.
7219 
7220 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7221 @*/
7222 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7223 {
7224   PetscInt i;
7225 
7226   PetscFunctionBegin;
7227   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7228   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7229   PetscAssertPointer(mat, 2);
7230 
7231   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7232 
7233   /* memory is allocated even if n = 0 */
7234   PetscCall(PetscFree(*mat));
7235   PetscFunctionReturn(PETSC_SUCCESS);
7236 }
7237 
7238 /*@C
7239   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7240 
7241   Collective
7242 
7243   Input Parameters:
7244 + n   - the number of local matrices
7245 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7246                        sequence of `MatCreateSubMatrices()`)
7247 
7248   Level: advanced
7249 
7250   Note:
7251   Frees not only the matrices, but also the array that contains the matrices
7252 
7253   Fortran Note:
7254   This does not free the array.
7255 
7256 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7257 @*/
7258 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7259 {
7260   Mat mat0;
7261 
7262   PetscFunctionBegin;
7263   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7264   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7265   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7266   PetscAssertPointer(mat, 2);
7267 
7268   mat0 = (*mat)[0];
7269   if (mat0 && mat0->ops->destroysubmatrices) {
7270     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7271   } else {
7272     PetscCall(MatDestroyMatrices(n, mat));
7273   }
7274   PetscFunctionReturn(PETSC_SUCCESS);
7275 }
7276 
7277 /*@C
7278   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7279 
7280   Collective
7281 
7282   Input Parameter:
7283 . mat - the matrix
7284 
7285   Output Parameter:
7286 . matstruct - the sequential matrix with the nonzero structure of mat
7287 
7288   Level: developer
7289 
7290 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7291 @*/
7292 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7293 {
7294   PetscFunctionBegin;
7295   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7296   PetscAssertPointer(matstruct, 2);
7297 
7298   PetscValidType(mat, 1);
7299   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7300   MatCheckPreallocated(mat, 1);
7301 
7302   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7303   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7304   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7305   PetscFunctionReturn(PETSC_SUCCESS);
7306 }
7307 
7308 /*@C
7309   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7310 
7311   Collective
7312 
7313   Input Parameter:
7314 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7315                        sequence of `MatGetSeqNonzeroStructure()`)
7316 
7317   Level: advanced
7318 
7319   Note:
7320   Frees not only the matrices, but also the array that contains the matrices
7321 
7322 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7323 @*/
7324 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7325 {
7326   PetscFunctionBegin;
7327   PetscAssertPointer(mat, 1);
7328   PetscCall(MatDestroy(mat));
7329   PetscFunctionReturn(PETSC_SUCCESS);
7330 }
7331 
7332 /*@
7333   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7334   replaces the index sets by larger ones that represent submatrices with
7335   additional overlap.
7336 
7337   Collective
7338 
7339   Input Parameters:
7340 + mat - the matrix
7341 . n   - the number of index sets
7342 . is  - the array of index sets (these index sets will changed during the call)
7343 - ov  - the additional overlap requested
7344 
7345   Options Database Key:
7346 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7347 
7348   Level: developer
7349 
7350   Note:
7351   The computed overlap preserves the matrix block sizes when the blocks are square.
7352   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7353   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7354 
7355 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7356 @*/
7357 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7358 {
7359   PetscInt i, bs, cbs;
7360 
7361   PetscFunctionBegin;
7362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7363   PetscValidType(mat, 1);
7364   PetscValidLogicalCollectiveInt(mat, n, 2);
7365   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7366   if (n) {
7367     PetscAssertPointer(is, 3);
7368     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7369   }
7370   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7371   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7372   MatCheckPreallocated(mat, 1);
7373 
7374   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7375   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7376   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7377   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7378   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7379   if (bs == cbs) {
7380     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7381   }
7382   PetscFunctionReturn(PETSC_SUCCESS);
7383 }
7384 
7385 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7386 
7387 /*@
7388   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7389   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7390   additional overlap.
7391 
7392   Collective
7393 
7394   Input Parameters:
7395 + mat - the matrix
7396 . n   - the number of index sets
7397 . is  - the array of index sets (these index sets will changed during the call)
7398 - ov  - the additional overlap requested
7399 
7400   `   Options Database Key:
7401 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7402 
7403   Level: developer
7404 
7405 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7406 @*/
7407 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7408 {
7409   PetscInt i;
7410 
7411   PetscFunctionBegin;
7412   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7413   PetscValidType(mat, 1);
7414   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7415   if (n) {
7416     PetscAssertPointer(is, 3);
7417     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7418   }
7419   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7420   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7421   MatCheckPreallocated(mat, 1);
7422   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7423   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7424   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7425   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7426   PetscFunctionReturn(PETSC_SUCCESS);
7427 }
7428 
7429 /*@
7430   MatGetBlockSize - Returns the matrix block size.
7431 
7432   Not Collective
7433 
7434   Input Parameter:
7435 . mat - the matrix
7436 
7437   Output Parameter:
7438 . bs - block size
7439 
7440   Level: intermediate
7441 
7442   Notes:
7443   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7444 
7445   If the block size has not been set yet this routine returns 1.
7446 
7447 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7448 @*/
7449 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7450 {
7451   PetscFunctionBegin;
7452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7453   PetscAssertPointer(bs, 2);
7454   *bs = PetscAbs(mat->rmap->bs);
7455   PetscFunctionReturn(PETSC_SUCCESS);
7456 }
7457 
7458 /*@
7459   MatGetBlockSizes - Returns the matrix block row and column sizes.
7460 
7461   Not Collective
7462 
7463   Input Parameter:
7464 . mat - the matrix
7465 
7466   Output Parameters:
7467 + rbs - row block size
7468 - cbs - column block size
7469 
7470   Level: intermediate
7471 
7472   Notes:
7473   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7474   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7475 
7476   If a block size has not been set yet this routine returns 1.
7477 
7478 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7479 @*/
7480 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7481 {
7482   PetscFunctionBegin;
7483   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7484   if (rbs) PetscAssertPointer(rbs, 2);
7485   if (cbs) PetscAssertPointer(cbs, 3);
7486   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7487   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7488   PetscFunctionReturn(PETSC_SUCCESS);
7489 }
7490 
7491 /*@
7492   MatSetBlockSize - Sets the matrix block size.
7493 
7494   Logically Collective
7495 
7496   Input Parameters:
7497 + mat - the matrix
7498 - bs  - block size
7499 
7500   Level: intermediate
7501 
7502   Notes:
7503   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7504   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7505 
7506   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7507   is compatible with the matrix local sizes.
7508 
7509 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7510 @*/
7511 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7512 {
7513   PetscFunctionBegin;
7514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7515   PetscValidLogicalCollectiveInt(mat, bs, 2);
7516   PetscCall(MatSetBlockSizes(mat, bs, bs));
7517   PetscFunctionReturn(PETSC_SUCCESS);
7518 }
7519 
7520 typedef struct {
7521   PetscInt         n;
7522   IS              *is;
7523   Mat             *mat;
7524   PetscObjectState nonzerostate;
7525   Mat              C;
7526 } EnvelopeData;
7527 
7528 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7529 {
7530   EnvelopeData *edata = (EnvelopeData *)ptr;
7531 
7532   PetscFunctionBegin;
7533   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7534   PetscCall(PetscFree(edata->is));
7535   PetscCall(PetscFree(edata));
7536   PetscFunctionReturn(PETSC_SUCCESS);
7537 }
7538 
7539 /*@
7540   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7541   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7542 
7543   Collective
7544 
7545   Input Parameter:
7546 . mat - the matrix
7547 
7548   Level: intermediate
7549 
7550   Notes:
7551   There can be zeros within the blocks
7552 
7553   The blocks can overlap between processes, including laying on more than two processes
7554 
7555 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7556 @*/
7557 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7558 {
7559   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7560   PetscInt          *diag, *odiag, sc;
7561   VecScatter         scatter;
7562   PetscScalar       *seqv;
7563   const PetscScalar *parv;
7564   const PetscInt    *ia, *ja;
7565   PetscBool          set, flag, done;
7566   Mat                AA = mat, A;
7567   MPI_Comm           comm;
7568   PetscMPIInt        rank, size, tag;
7569   MPI_Status         status;
7570   PetscContainer     container;
7571   EnvelopeData      *edata;
7572   Vec                seq, par;
7573   IS                 isglobal;
7574 
7575   PetscFunctionBegin;
7576   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7577   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7578   if (!set || !flag) {
7579     /* TODO: only needs nonzero structure of transpose */
7580     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7581     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7582   }
7583   PetscCall(MatAIJGetLocalMat(AA, &A));
7584   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7585   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7586 
7587   PetscCall(MatGetLocalSize(mat, &n, NULL));
7588   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7589   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7590   PetscCallMPI(MPI_Comm_size(comm, &size));
7591   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7592 
7593   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7594 
7595   if (rank > 0) {
7596     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7597     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7598   }
7599   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7600   for (i = 0; i < n; i++) {
7601     env = PetscMax(env, ja[ia[i + 1] - 1]);
7602     II  = rstart + i;
7603     if (env == II) {
7604       starts[lblocks]  = tbs;
7605       sizes[lblocks++] = 1 + II - tbs;
7606       tbs              = 1 + II;
7607     }
7608   }
7609   if (rank < size - 1) {
7610     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7611     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7612   }
7613 
7614   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7615   if (!set || !flag) PetscCall(MatDestroy(&AA));
7616   PetscCall(MatDestroy(&A));
7617 
7618   PetscCall(PetscNew(&edata));
7619   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7620   edata->n = lblocks;
7621   /* create IS needed for extracting blocks from the original matrix */
7622   PetscCall(PetscMalloc1(lblocks, &edata->is));
7623   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7624 
7625   /* Create the resulting inverse matrix structure with preallocation information */
7626   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7627   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7628   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7629   PetscCall(MatSetType(edata->C, MATAIJ));
7630 
7631   /* Communicate the start and end of each row, from each block to the correct rank */
7632   /* TODO: Use PetscSF instead of VecScatter */
7633   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7634   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7635   PetscCall(VecGetArrayWrite(seq, &seqv));
7636   for (PetscInt i = 0; i < lblocks; i++) {
7637     for (PetscInt j = 0; j < sizes[i]; j++) {
7638       seqv[cnt]     = starts[i];
7639       seqv[cnt + 1] = starts[i] + sizes[i];
7640       cnt += 2;
7641     }
7642   }
7643   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7644   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7645   sc -= cnt;
7646   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7647   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7648   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7649   PetscCall(ISDestroy(&isglobal));
7650   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7651   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7652   PetscCall(VecScatterDestroy(&scatter));
7653   PetscCall(VecDestroy(&seq));
7654   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7655   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7656   PetscCall(VecGetArrayRead(par, &parv));
7657   cnt = 0;
7658   PetscCall(MatGetSize(mat, NULL, &n));
7659   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7660     PetscInt start, end, d = 0, od = 0;
7661 
7662     start = (PetscInt)PetscRealPart(parv[cnt]);
7663     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7664     cnt += 2;
7665 
7666     if (start < cstart) {
7667       od += cstart - start + n - cend;
7668       d += cend - cstart;
7669     } else if (start < cend) {
7670       od += n - cend;
7671       d += cend - start;
7672     } else od += n - start;
7673     if (end <= cstart) {
7674       od -= cstart - end + n - cend;
7675       d -= cend - cstart;
7676     } else if (end < cend) {
7677       od -= n - cend;
7678       d -= cend - end;
7679     } else od -= n - end;
7680 
7681     odiag[i] = od;
7682     diag[i]  = d;
7683   }
7684   PetscCall(VecRestoreArrayRead(par, &parv));
7685   PetscCall(VecDestroy(&par));
7686   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7687   PetscCall(PetscFree2(diag, odiag));
7688   PetscCall(PetscFree2(sizes, starts));
7689 
7690   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7691   PetscCall(PetscContainerSetPointer(container, edata));
7692   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7693   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7694   PetscCall(PetscObjectDereference((PetscObject)container));
7695   PetscFunctionReturn(PETSC_SUCCESS);
7696 }
7697 
7698 /*@
7699   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7700 
7701   Collective
7702 
7703   Input Parameters:
7704 + A     - the matrix
7705 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7706 
7707   Output Parameter:
7708 . C - matrix with inverted block diagonal of `A`
7709 
7710   Level: advanced
7711 
7712   Note:
7713   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7714 
7715 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7716 @*/
7717 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7718 {
7719   PetscContainer   container;
7720   EnvelopeData    *edata;
7721   PetscObjectState nonzerostate;
7722 
7723   PetscFunctionBegin;
7724   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7725   if (!container) {
7726     PetscCall(MatComputeVariableBlockEnvelope(A));
7727     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7728   }
7729   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7730   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7731   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7732   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7733 
7734   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7735   *C = edata->C;
7736 
7737   for (PetscInt i = 0; i < edata->n; i++) {
7738     Mat          D;
7739     PetscScalar *dvalues;
7740 
7741     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7742     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7743     PetscCall(MatSeqDenseInvert(D));
7744     PetscCall(MatDenseGetArray(D, &dvalues));
7745     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7746     PetscCall(MatDestroy(&D));
7747   }
7748   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7749   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7750   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7751   PetscFunctionReturn(PETSC_SUCCESS);
7752 }
7753 
7754 /*@
7755   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7756 
7757   Logically Collective
7758 
7759   Input Parameters:
7760 + mat     - the matrix
7761 . nblocks - the number of blocks on this process, each block can only exist on a single process
7762 - bsizes  - the block sizes
7763 
7764   Level: intermediate
7765 
7766   Notes:
7767   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7768 
7769   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.
7770 
7771 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7772           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7773 @*/
7774 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7775 {
7776   PetscInt i, ncnt = 0, nlocal;
7777 
7778   PetscFunctionBegin;
7779   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7780   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7781   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);
7782   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7783   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);
7784   PetscCall(PetscFree(mat->bsizes));
7785   mat->nblocks = nblocks;
7786   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7787   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7788   PetscFunctionReturn(PETSC_SUCCESS);
7789 }
7790 
7791 /*@C
7792   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7793 
7794   Logically Collective; No Fortran Support
7795 
7796   Input Parameter:
7797 . mat - the matrix
7798 
7799   Output Parameters:
7800 + nblocks - the number of blocks on this process
7801 - bsizes  - the block sizes
7802 
7803   Level: intermediate
7804 
7805 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7806 @*/
7807 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7808 {
7809   PetscFunctionBegin;
7810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7811   *nblocks = mat->nblocks;
7812   *bsizes  = mat->bsizes;
7813   PetscFunctionReturn(PETSC_SUCCESS);
7814 }
7815 
7816 /*@
7817   MatSetBlockSizes - Sets the matrix block row and column sizes.
7818 
7819   Logically Collective
7820 
7821   Input Parameters:
7822 + mat - the matrix
7823 . rbs - row block size
7824 - cbs - column block size
7825 
7826   Level: intermediate
7827 
7828   Notes:
7829   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7830   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7831   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7832 
7833   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7834   are compatible with the matrix local sizes.
7835 
7836   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7837 
7838 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7839 @*/
7840 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7841 {
7842   PetscFunctionBegin;
7843   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7844   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7845   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7846   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7847   if (mat->rmap->refcnt) {
7848     ISLocalToGlobalMapping l2g  = NULL;
7849     PetscLayout            nmap = NULL;
7850 
7851     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7852     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7853     PetscCall(PetscLayoutDestroy(&mat->rmap));
7854     mat->rmap          = nmap;
7855     mat->rmap->mapping = l2g;
7856   }
7857   if (mat->cmap->refcnt) {
7858     ISLocalToGlobalMapping l2g  = NULL;
7859     PetscLayout            nmap = NULL;
7860 
7861     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7862     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7863     PetscCall(PetscLayoutDestroy(&mat->cmap));
7864     mat->cmap          = nmap;
7865     mat->cmap->mapping = l2g;
7866   }
7867   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7868   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7869   PetscFunctionReturn(PETSC_SUCCESS);
7870 }
7871 
7872 /*@
7873   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7874 
7875   Logically Collective
7876 
7877   Input Parameters:
7878 + mat     - the matrix
7879 . fromRow - matrix from which to copy row block size
7880 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7881 
7882   Level: developer
7883 
7884 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7885 @*/
7886 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7887 {
7888   PetscFunctionBegin;
7889   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7890   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7891   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7892   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7893   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7894   PetscFunctionReturn(PETSC_SUCCESS);
7895 }
7896 
7897 /*@
7898   MatResidual - Default routine to calculate the residual r = b - Ax
7899 
7900   Collective
7901 
7902   Input Parameters:
7903 + mat - the matrix
7904 . b   - the right-hand-side
7905 - x   - the approximate solution
7906 
7907   Output Parameter:
7908 . r - location to store the residual
7909 
7910   Level: developer
7911 
7912 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7913 @*/
7914 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7915 {
7916   PetscFunctionBegin;
7917   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7918   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7919   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7920   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7921   PetscValidType(mat, 1);
7922   MatCheckPreallocated(mat, 1);
7923   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7924   if (!mat->ops->residual) {
7925     PetscCall(MatMult(mat, x, r));
7926     PetscCall(VecAYPX(r, -1.0, b));
7927   } else {
7928     PetscUseTypeMethod(mat, residual, b, x, r);
7929   }
7930   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7931   PetscFunctionReturn(PETSC_SUCCESS);
7932 }
7933 
7934 /*MC
7935     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7936 
7937     Synopsis:
7938     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7939 
7940     Not Collective
7941 
7942     Input Parameters:
7943 +   A - the matrix
7944 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7945 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7946 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7947                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7948                  always used.
7949 
7950     Output Parameters:
7951 +   n - number of local rows in the (possibly compressed) matrix
7952 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7953 .   ja - the column indices
7954 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7955            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7956 
7957     Level: developer
7958 
7959     Note:
7960     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7961 
7962 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7963 M*/
7964 
7965 /*MC
7966     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7967 
7968     Synopsis:
7969     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7970 
7971     Not Collective
7972 
7973     Input Parameters:
7974 +   A - the  matrix
7975 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7976 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7977     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7978                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7979                  always used.
7980 .   n - number of local rows in the (possibly compressed) matrix
7981 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7982 .   ja - the column indices
7983 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7984            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7985 
7986     Level: developer
7987 
7988 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7989 M*/
7990 
7991 /*@C
7992   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7993 
7994   Collective
7995 
7996   Input Parameters:
7997 + mat             - the matrix
7998 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7999 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8000 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8001                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8002                  always used.
8003 
8004   Output Parameters:
8005 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8006 . 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
8007 . ja   - the column indices, use `NULL` if not needed
8008 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8009            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8010 
8011   Level: developer
8012 
8013   Notes:
8014   You CANNOT change any of the ia[] or ja[] values.
8015 
8016   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8017 
8018   Fortran Notes:
8019   Use
8020 .vb
8021     PetscInt, pointer :: ia(:),ja(:)
8022     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8023     ! Access the ith and jth entries via ia(i) and ja(j)
8024 .ve
8025 
8026   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8027 
8028 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8029 @*/
8030 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8031 {
8032   PetscFunctionBegin;
8033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8034   PetscValidType(mat, 1);
8035   if (n) PetscAssertPointer(n, 5);
8036   if (ia) PetscAssertPointer(ia, 6);
8037   if (ja) PetscAssertPointer(ja, 7);
8038   if (done) PetscAssertPointer(done, 8);
8039   MatCheckPreallocated(mat, 1);
8040   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8041   else {
8042     if (done) *done = PETSC_TRUE;
8043     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8044     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8045     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8046   }
8047   PetscFunctionReturn(PETSC_SUCCESS);
8048 }
8049 
8050 /*@C
8051   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8052 
8053   Collective
8054 
8055   Input Parameters:
8056 + mat             - the matrix
8057 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8058 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8059                 symmetrized
8060 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8061                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8062                  always used.
8063 . n               - number of columns in the (possibly compressed) matrix
8064 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8065 - ja              - the row indices
8066 
8067   Output Parameter:
8068 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8069 
8070   Level: developer
8071 
8072 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8073 @*/
8074 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8075 {
8076   PetscFunctionBegin;
8077   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8078   PetscValidType(mat, 1);
8079   PetscAssertPointer(n, 5);
8080   if (ia) PetscAssertPointer(ia, 6);
8081   if (ja) PetscAssertPointer(ja, 7);
8082   PetscAssertPointer(done, 8);
8083   MatCheckPreallocated(mat, 1);
8084   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8085   else {
8086     *done = PETSC_TRUE;
8087     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8088   }
8089   PetscFunctionReturn(PETSC_SUCCESS);
8090 }
8091 
8092 /*@C
8093   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8094 
8095   Collective
8096 
8097   Input Parameters:
8098 + mat             - the matrix
8099 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8100 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8101 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8102                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8103                  always used.
8104 . n               - size of (possibly compressed) matrix
8105 . ia              - the row pointers
8106 - ja              - the column indices
8107 
8108   Output Parameter:
8109 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8110 
8111   Level: developer
8112 
8113   Note:
8114   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8115   us of the array after it has been restored. If you pass `NULL`, it will
8116   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8117 
8118   Fortran Note:
8119   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8120 
8121 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8122 @*/
8123 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8124 {
8125   PetscFunctionBegin;
8126   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8127   PetscValidType(mat, 1);
8128   if (ia) PetscAssertPointer(ia, 6);
8129   if (ja) PetscAssertPointer(ja, 7);
8130   if (done) PetscAssertPointer(done, 8);
8131   MatCheckPreallocated(mat, 1);
8132 
8133   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8134   else {
8135     if (done) *done = PETSC_TRUE;
8136     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8137     if (n) *n = 0;
8138     if (ia) *ia = NULL;
8139     if (ja) *ja = NULL;
8140   }
8141   PetscFunctionReturn(PETSC_SUCCESS);
8142 }
8143 
8144 /*@C
8145   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8146 
8147   Collective
8148 
8149   Input Parameters:
8150 + mat             - the matrix
8151 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8152 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8153 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8154                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8155                  always used.
8156 
8157   Output Parameters:
8158 + n    - size of (possibly compressed) matrix
8159 . ia   - the column pointers
8160 . ja   - the row indices
8161 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8162 
8163   Level: developer
8164 
8165 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8166 @*/
8167 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8168 {
8169   PetscFunctionBegin;
8170   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8171   PetscValidType(mat, 1);
8172   if (ia) PetscAssertPointer(ia, 6);
8173   if (ja) PetscAssertPointer(ja, 7);
8174   PetscAssertPointer(done, 8);
8175   MatCheckPreallocated(mat, 1);
8176 
8177   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8178   else {
8179     *done = PETSC_TRUE;
8180     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8181     if (n) *n = 0;
8182     if (ia) *ia = NULL;
8183     if (ja) *ja = NULL;
8184   }
8185   PetscFunctionReturn(PETSC_SUCCESS);
8186 }
8187 
8188 /*@C
8189   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8190   `MatGetColumnIJ()`.
8191 
8192   Collective
8193 
8194   Input Parameters:
8195 + mat        - the matrix
8196 . ncolors    - maximum color value
8197 . n          - number of entries in colorarray
8198 - colorarray - array indicating color for each column
8199 
8200   Output Parameter:
8201 . iscoloring - coloring generated using colorarray information
8202 
8203   Level: developer
8204 
8205 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8206 @*/
8207 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8208 {
8209   PetscFunctionBegin;
8210   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8211   PetscValidType(mat, 1);
8212   PetscAssertPointer(colorarray, 4);
8213   PetscAssertPointer(iscoloring, 5);
8214   MatCheckPreallocated(mat, 1);
8215 
8216   if (!mat->ops->coloringpatch) {
8217     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8218   } else {
8219     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8220   }
8221   PetscFunctionReturn(PETSC_SUCCESS);
8222 }
8223 
8224 /*@
8225   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8226 
8227   Logically Collective
8228 
8229   Input Parameter:
8230 . mat - the factored matrix to be reset
8231 
8232   Level: developer
8233 
8234   Notes:
8235   This routine should be used only with factored matrices formed by in-place
8236   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8237   format).  This option can save memory, for example, when solving nonlinear
8238   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8239   ILU(0) preconditioner.
8240 
8241   One can specify in-place ILU(0) factorization by calling
8242 .vb
8243      PCType(pc,PCILU);
8244      PCFactorSeUseInPlace(pc);
8245 .ve
8246   or by using the options -pc_type ilu -pc_factor_in_place
8247 
8248   In-place factorization ILU(0) can also be used as a local
8249   solver for the blocks within the block Jacobi or additive Schwarz
8250   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8251   for details on setting local solver options.
8252 
8253   Most users should employ the `KSP` interface for linear solvers
8254   instead of working directly with matrix algebra routines such as this.
8255   See, e.g., `KSPCreate()`.
8256 
8257 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8258 @*/
8259 PetscErrorCode MatSetUnfactored(Mat mat)
8260 {
8261   PetscFunctionBegin;
8262   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8263   PetscValidType(mat, 1);
8264   MatCheckPreallocated(mat, 1);
8265   mat->factortype = MAT_FACTOR_NONE;
8266   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8267   PetscUseTypeMethod(mat, setunfactored);
8268   PetscFunctionReturn(PETSC_SUCCESS);
8269 }
8270 
8271 /*MC
8272     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8273 
8274     Synopsis:
8275     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8276 
8277     Not Collective
8278 
8279     Input Parameter:
8280 .   x - matrix
8281 
8282     Output Parameters:
8283 +   xx_v - the Fortran pointer to the array
8284 -   ierr - error code
8285 
8286     Example of Usage:
8287 .vb
8288       PetscScalar, pointer xx_v(:,:)
8289       ....
8290       call MatDenseGetArrayF90(x,xx_v,ierr)
8291       a = xx_v(3)
8292       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8293 .ve
8294 
8295     Level: advanced
8296 
8297 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8298 M*/
8299 
8300 /*MC
8301     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8302     accessed with `MatDenseGetArrayF90()`.
8303 
8304     Synopsis:
8305     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8306 
8307     Not Collective
8308 
8309     Input Parameters:
8310 +   x - matrix
8311 -   xx_v - the Fortran90 pointer to the array
8312 
8313     Output Parameter:
8314 .   ierr - error code
8315 
8316     Example of Usage:
8317 .vb
8318        PetscScalar, pointer xx_v(:,:)
8319        ....
8320        call MatDenseGetArrayF90(x,xx_v,ierr)
8321        a = xx_v(3)
8322        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8323 .ve
8324 
8325     Level: advanced
8326 
8327 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8328 M*/
8329 
8330 /*MC
8331     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8332 
8333     Synopsis:
8334     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8335 
8336     Not Collective
8337 
8338     Input Parameter:
8339 .   x - matrix
8340 
8341     Output Parameters:
8342 +   xx_v - the Fortran pointer to the array
8343 -   ierr - error code
8344 
8345     Example of Usage:
8346 .vb
8347       PetscScalar, pointer xx_v(:)
8348       ....
8349       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8350       a = xx_v(3)
8351       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8352 .ve
8353 
8354     Level: advanced
8355 
8356 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8357 M*/
8358 
8359 /*MC
8360     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8361     accessed with `MatSeqAIJGetArrayF90()`.
8362 
8363     Synopsis:
8364     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8365 
8366     Not Collective
8367 
8368     Input Parameters:
8369 +   x - matrix
8370 -   xx_v - the Fortran90 pointer to the array
8371 
8372     Output Parameter:
8373 .   ierr - error code
8374 
8375     Example of Usage:
8376 .vb
8377        PetscScalar, pointer xx_v(:)
8378        ....
8379        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8380        a = xx_v(3)
8381        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8382 .ve
8383 
8384     Level: advanced
8385 
8386 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8387 M*/
8388 
8389 /*@
8390   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8391   as the original matrix.
8392 
8393   Collective
8394 
8395   Input Parameters:
8396 + mat   - the original matrix
8397 . isrow - parallel `IS` containing the rows this processor should obtain
8398 . 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.
8399 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8400 
8401   Output Parameter:
8402 . newmat - the new submatrix, of the same type as the original matrix
8403 
8404   Level: advanced
8405 
8406   Notes:
8407   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8408 
8409   Some matrix types place restrictions on the row and column indices, such
8410   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;
8411   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8412 
8413   The index sets may not have duplicate entries.
8414 
8415   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8416   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8417   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8418   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8419   you are finished using it.
8420 
8421   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8422   the input matrix.
8423 
8424   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8425 
8426   If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature
8427   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8428 
8429   Example usage:
8430   Consider the following 8x8 matrix with 34 non-zero values, that is
8431   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8432   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8433   as follows
8434 .vb
8435             1  2  0  |  0  3  0  |  0  4
8436     Proc0   0  5  6  |  7  0  0  |  8  0
8437             9  0 10  | 11  0  0  | 12  0
8438     -------------------------------------
8439            13  0 14  | 15 16 17  |  0  0
8440     Proc1   0 18  0  | 19 20 21  |  0  0
8441             0  0  0  | 22 23  0  | 24  0
8442     -------------------------------------
8443     Proc2  25 26 27  |  0  0 28  | 29  0
8444            30  0  0  | 31 32 33  |  0 34
8445 .ve
8446 
8447   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8448 
8449 .vb
8450             2  0  |  0  3  0  |  0
8451     Proc0   5  6  |  7  0  0  |  8
8452     -------------------------------
8453     Proc1  18  0  | 19 20 21  |  0
8454     -------------------------------
8455     Proc2  26 27  |  0  0 28  | 29
8456             0  0  | 31 32 33  |  0
8457 .ve
8458 
8459 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8460 @*/
8461 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8462 {
8463   PetscMPIInt size;
8464   Mat        *local;
8465   IS          iscoltmp;
8466   PetscBool   flg;
8467 
8468   PetscFunctionBegin;
8469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8470   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8471   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8472   PetscAssertPointer(newmat, 5);
8473   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8474   PetscValidType(mat, 1);
8475   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8476   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8477 
8478   MatCheckPreallocated(mat, 1);
8479   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8480 
8481   if (!iscol || isrow == iscol) {
8482     PetscBool   stride;
8483     PetscMPIInt grabentirematrix = 0, grab;
8484     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8485     if (stride) {
8486       PetscInt first, step, n, rstart, rend;
8487       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8488       if (step == 1) {
8489         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8490         if (rstart == first) {
8491           PetscCall(ISGetLocalSize(isrow, &n));
8492           if (n == rend - rstart) grabentirematrix = 1;
8493         }
8494       }
8495     }
8496     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8497     if (grab) {
8498       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8499       if (cll == MAT_INITIAL_MATRIX) {
8500         *newmat = mat;
8501         PetscCall(PetscObjectReference((PetscObject)mat));
8502       }
8503       PetscFunctionReturn(PETSC_SUCCESS);
8504     }
8505   }
8506 
8507   if (!iscol) {
8508     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8509   } else {
8510     iscoltmp = iscol;
8511   }
8512 
8513   /* if original matrix is on just one processor then use submatrix generated */
8514   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8515     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8516     goto setproperties;
8517   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8518     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8519     *newmat = *local;
8520     PetscCall(PetscFree(local));
8521     goto setproperties;
8522   } else if (!mat->ops->createsubmatrix) {
8523     /* Create a new matrix type that implements the operation using the full matrix */
8524     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8525     switch (cll) {
8526     case MAT_INITIAL_MATRIX:
8527       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8528       break;
8529     case MAT_REUSE_MATRIX:
8530       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8531       break;
8532     default:
8533       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8534     }
8535     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8536     goto setproperties;
8537   }
8538 
8539   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8540   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8541   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8542 
8543 setproperties:
8544   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8545   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8546   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8547   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8548   PetscFunctionReturn(PETSC_SUCCESS);
8549 }
8550 
8551 /*@
8552   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8553 
8554   Not Collective
8555 
8556   Input Parameters:
8557 + A - the matrix we wish to propagate options from
8558 - B - the matrix we wish to propagate options to
8559 
8560   Level: beginner
8561 
8562   Note:
8563   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8564 
8565 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8566 @*/
8567 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8568 {
8569   PetscFunctionBegin;
8570   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8571   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8572   B->symmetry_eternal            = A->symmetry_eternal;
8573   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8574   B->symmetric                   = A->symmetric;
8575   B->structurally_symmetric      = A->structurally_symmetric;
8576   B->spd                         = A->spd;
8577   B->hermitian                   = A->hermitian;
8578   PetscFunctionReturn(PETSC_SUCCESS);
8579 }
8580 
8581 /*@
8582   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8583   used during the assembly process to store values that belong to
8584   other processors.
8585 
8586   Not Collective
8587 
8588   Input Parameters:
8589 + mat   - the matrix
8590 . size  - the initial size of the stash.
8591 - bsize - the initial size of the block-stash(if used).
8592 
8593   Options Database Keys:
8594 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8595 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8596 
8597   Level: intermediate
8598 
8599   Notes:
8600   The block-stash is used for values set with `MatSetValuesBlocked()` while
8601   the stash is used for values set with `MatSetValues()`
8602 
8603   Run with the option -info and look for output of the form
8604   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8605   to determine the appropriate value, MM, to use for size and
8606   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8607   to determine the value, BMM to use for bsize
8608 
8609 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8610 @*/
8611 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8612 {
8613   PetscFunctionBegin;
8614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8615   PetscValidType(mat, 1);
8616   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8617   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8618   PetscFunctionReturn(PETSC_SUCCESS);
8619 }
8620 
8621 /*@
8622   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8623   the matrix
8624 
8625   Neighbor-wise Collective
8626 
8627   Input Parameters:
8628 + A - the matrix
8629 . x - the vector to be multiplied by the interpolation operator
8630 - y - the vector to be added to the result
8631 
8632   Output Parameter:
8633 . w - the resulting vector
8634 
8635   Level: intermediate
8636 
8637   Notes:
8638   `w` may be the same vector as `y`.
8639 
8640   This allows one to use either the restriction or interpolation (its transpose)
8641   matrix to do the interpolation
8642 
8643 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8644 @*/
8645 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8646 {
8647   PetscInt M, N, Ny;
8648 
8649   PetscFunctionBegin;
8650   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8651   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8652   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8653   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8654   PetscCall(MatGetSize(A, &M, &N));
8655   PetscCall(VecGetSize(y, &Ny));
8656   if (M == Ny) {
8657     PetscCall(MatMultAdd(A, x, y, w));
8658   } else {
8659     PetscCall(MatMultTransposeAdd(A, x, y, w));
8660   }
8661   PetscFunctionReturn(PETSC_SUCCESS);
8662 }
8663 
8664 /*@
8665   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8666   the matrix
8667 
8668   Neighbor-wise Collective
8669 
8670   Input Parameters:
8671 + A - the matrix
8672 - x - the vector to be interpolated
8673 
8674   Output Parameter:
8675 . y - the resulting vector
8676 
8677   Level: intermediate
8678 
8679   Note:
8680   This allows one to use either the restriction or interpolation (its transpose)
8681   matrix to do the interpolation
8682 
8683 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8684 @*/
8685 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8686 {
8687   PetscInt M, N, Ny;
8688 
8689   PetscFunctionBegin;
8690   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8691   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8692   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8693   PetscCall(MatGetSize(A, &M, &N));
8694   PetscCall(VecGetSize(y, &Ny));
8695   if (M == Ny) {
8696     PetscCall(MatMult(A, x, y));
8697   } else {
8698     PetscCall(MatMultTranspose(A, x, y));
8699   }
8700   PetscFunctionReturn(PETSC_SUCCESS);
8701 }
8702 
8703 /*@
8704   MatRestrict - $y = A*x$ or $A^T*x$
8705 
8706   Neighbor-wise Collective
8707 
8708   Input Parameters:
8709 + A - the matrix
8710 - x - the vector to be restricted
8711 
8712   Output Parameter:
8713 . y - the resulting vector
8714 
8715   Level: intermediate
8716 
8717   Note:
8718   This allows one to use either the restriction or interpolation (its transpose)
8719   matrix to do the restriction
8720 
8721 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8722 @*/
8723 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8724 {
8725   PetscInt M, N, Nx;
8726 
8727   PetscFunctionBegin;
8728   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8729   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8730   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8731   PetscCall(MatGetSize(A, &M, &N));
8732   PetscCall(VecGetSize(x, &Nx));
8733   if (M == Nx) {
8734     PetscCall(MatMultTranspose(A, x, y));
8735   } else {
8736     PetscCall(MatMult(A, x, y));
8737   }
8738   PetscFunctionReturn(PETSC_SUCCESS);
8739 }
8740 
8741 /*@
8742   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8743 
8744   Neighbor-wise Collective
8745 
8746   Input Parameters:
8747 + A - the matrix
8748 . x - the input dense matrix to be multiplied
8749 - w - the input dense matrix to be added to the result
8750 
8751   Output Parameter:
8752 . y - the output dense matrix
8753 
8754   Level: intermediate
8755 
8756   Note:
8757   This allows one to use either the restriction or interpolation (its transpose)
8758   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8759   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8760 
8761 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8762 @*/
8763 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8764 {
8765   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8766   PetscBool trans = PETSC_TRUE;
8767   MatReuse  reuse = MAT_INITIAL_MATRIX;
8768 
8769   PetscFunctionBegin;
8770   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8771   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8772   PetscValidType(x, 2);
8773   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8774   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8775   PetscCall(MatGetSize(A, &M, &N));
8776   PetscCall(MatGetSize(x, &Mx, &Nx));
8777   if (N == Mx) trans = PETSC_FALSE;
8778   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);
8779   Mo = trans ? N : M;
8780   if (*y) {
8781     PetscCall(MatGetSize(*y, &My, &Ny));
8782     if (Mo == My && Nx == Ny) {
8783       reuse = MAT_REUSE_MATRIX;
8784     } else {
8785       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);
8786       PetscCall(MatDestroy(y));
8787     }
8788   }
8789 
8790   if (w && *y == w) { /* this is to minimize changes in PCMG */
8791     PetscBool flg;
8792 
8793     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8794     if (w) {
8795       PetscInt My, Ny, Mw, Nw;
8796 
8797       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8798       PetscCall(MatGetSize(*y, &My, &Ny));
8799       PetscCall(MatGetSize(w, &Mw, &Nw));
8800       if (!flg || My != Mw || Ny != Nw) w = NULL;
8801     }
8802     if (!w) {
8803       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8804       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8805       PetscCall(PetscObjectDereference((PetscObject)w));
8806     } else {
8807       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8808     }
8809   }
8810   if (!trans) {
8811     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8812   } else {
8813     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8814   }
8815   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8816   PetscFunctionReturn(PETSC_SUCCESS);
8817 }
8818 
8819 /*@
8820   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8821 
8822   Neighbor-wise Collective
8823 
8824   Input Parameters:
8825 + A - the matrix
8826 - x - the input dense matrix
8827 
8828   Output Parameter:
8829 . y - the output dense matrix
8830 
8831   Level: intermediate
8832 
8833   Note:
8834   This allows one to use either the restriction or interpolation (its transpose)
8835   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8836   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8837 
8838 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8839 @*/
8840 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8841 {
8842   PetscFunctionBegin;
8843   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8844   PetscFunctionReturn(PETSC_SUCCESS);
8845 }
8846 
8847 /*@
8848   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8849 
8850   Neighbor-wise Collective
8851 
8852   Input Parameters:
8853 + A - the matrix
8854 - x - the input dense matrix
8855 
8856   Output Parameter:
8857 . y - the output dense matrix
8858 
8859   Level: intermediate
8860 
8861   Note:
8862   This allows one to use either the restriction or interpolation (its transpose)
8863   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8864   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8865 
8866 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8867 @*/
8868 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8869 {
8870   PetscFunctionBegin;
8871   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8872   PetscFunctionReturn(PETSC_SUCCESS);
8873 }
8874 
8875 /*@
8876   MatGetNullSpace - retrieves the null space of a matrix.
8877 
8878   Logically Collective
8879 
8880   Input Parameters:
8881 + mat    - the matrix
8882 - nullsp - the null space object
8883 
8884   Level: developer
8885 
8886 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8887 @*/
8888 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8889 {
8890   PetscFunctionBegin;
8891   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8892   PetscAssertPointer(nullsp, 2);
8893   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8894   PetscFunctionReturn(PETSC_SUCCESS);
8895 }
8896 
8897 /*@C
8898   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8899 
8900   Logically Collective
8901 
8902   Input Parameters:
8903 + n   - the number of matrices
8904 - mat - the array of matrices
8905 
8906   Output Parameters:
8907 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space
8908 
8909   Level: developer
8910 
8911   Note:
8912   Call `MatRestoreNullspaces()` to provide these to another array of matrices
8913 
8914 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8915           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
8916 @*/
8917 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8918 {
8919   PetscFunctionBegin;
8920   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8921   PetscAssertPointer(mat, 2);
8922   PetscAssertPointer(nullsp, 3);
8923 
8924   PetscCall(PetscCalloc1(3 * n, nullsp));
8925   for (PetscInt i = 0; i < n; i++) {
8926     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8927     (*nullsp)[i] = mat[i]->nullsp;
8928     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
8929     (*nullsp)[n + i] = mat[i]->nearnullsp;
8930     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
8931     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
8932     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
8933   }
8934   PetscFunctionReturn(PETSC_SUCCESS);
8935 }
8936 
8937 /*@C
8938   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
8939 
8940   Logically Collective
8941 
8942   Input Parameters:
8943 + n      - the number of matrices
8944 . mat    - the array of matrices
8945 - nullsp - an array of null spaces, `NULL` if the null space does not exist
8946 
8947   Level: developer
8948 
8949   Note:
8950   Call `MatGetNullSpaces()` to create `nullsp`
8951 
8952 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
8953           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
8954 @*/
8955 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
8956 {
8957   PetscFunctionBegin;
8958   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
8959   PetscAssertPointer(mat, 2);
8960   PetscAssertPointer(nullsp, 3);
8961   PetscAssertPointer(*nullsp, 3);
8962 
8963   for (PetscInt i = 0; i < n; i++) {
8964     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
8965     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
8966     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
8967     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
8968     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
8969     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
8970     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
8971   }
8972   PetscCall(PetscFree(*nullsp));
8973   PetscFunctionReturn(PETSC_SUCCESS);
8974 }
8975 
8976 /*@
8977   MatSetNullSpace - attaches a null space to a matrix.
8978 
8979   Logically Collective
8980 
8981   Input Parameters:
8982 + mat    - the matrix
8983 - nullsp - the null space object
8984 
8985   Level: advanced
8986 
8987   Notes:
8988   This null space is used by the `KSP` linear solvers to solve singular systems.
8989 
8990   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`
8991 
8992   For inconsistent singular systems (linear systems where the right hand side is not in the range of the operator) the `KSP` residuals will not converge to
8993   to zero but the linear system will still be solved in a least squares sense.
8994 
8995   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8996   the domain of a matrix A (from $R^n$ to $R^m$ (m rows, n columns) $R^n$ = the direct sum of the null space of A, n(A), + the range of $A^T$, $R(A^T)$.
8997   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
8998   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
8999   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$).
9000   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9001 
9002   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9003   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9004   routine also automatically calls `MatSetTransposeNullSpace()`.
9005 
9006   The user should call `MatNullSpaceDestroy()`.
9007 
9008 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9009           `KSPSetPCSide()`
9010 @*/
9011 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9012 {
9013   PetscFunctionBegin;
9014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9015   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9016   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9017   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9018   mat->nullsp = nullsp;
9019   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9020   PetscFunctionReturn(PETSC_SUCCESS);
9021 }
9022 
9023 /*@
9024   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9025 
9026   Logically Collective
9027 
9028   Input Parameters:
9029 + mat    - the matrix
9030 - nullsp - the null space object
9031 
9032   Level: developer
9033 
9034 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9035 @*/
9036 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9037 {
9038   PetscFunctionBegin;
9039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9040   PetscValidType(mat, 1);
9041   PetscAssertPointer(nullsp, 2);
9042   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9043   PetscFunctionReturn(PETSC_SUCCESS);
9044 }
9045 
9046 /*@
9047   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9048 
9049   Logically Collective
9050 
9051   Input Parameters:
9052 + mat    - the matrix
9053 - nullsp - the null space object
9054 
9055   Level: advanced
9056 
9057   Notes:
9058   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9059 
9060   See `MatSetNullSpace()`
9061 
9062 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9063 @*/
9064 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9065 {
9066   PetscFunctionBegin;
9067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9068   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9069   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9070   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9071   mat->transnullsp = nullsp;
9072   PetscFunctionReturn(PETSC_SUCCESS);
9073 }
9074 
9075 /*@
9076   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9077   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9078 
9079   Logically Collective
9080 
9081   Input Parameters:
9082 + mat    - the matrix
9083 - nullsp - the null space object
9084 
9085   Level: advanced
9086 
9087   Notes:
9088   Overwrites any previous near null space that may have been attached
9089 
9090   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9091 
9092 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9093 @*/
9094 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9095 {
9096   PetscFunctionBegin;
9097   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9098   PetscValidType(mat, 1);
9099   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9100   MatCheckPreallocated(mat, 1);
9101   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9102   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9103   mat->nearnullsp = nullsp;
9104   PetscFunctionReturn(PETSC_SUCCESS);
9105 }
9106 
9107 /*@
9108   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9109 
9110   Not Collective
9111 
9112   Input Parameter:
9113 . mat - the matrix
9114 
9115   Output Parameter:
9116 . nullsp - the null space object, `NULL` if not set
9117 
9118   Level: advanced
9119 
9120 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9121 @*/
9122 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9123 {
9124   PetscFunctionBegin;
9125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9126   PetscValidType(mat, 1);
9127   PetscAssertPointer(nullsp, 2);
9128   MatCheckPreallocated(mat, 1);
9129   *nullsp = mat->nearnullsp;
9130   PetscFunctionReturn(PETSC_SUCCESS);
9131 }
9132 
9133 /*@C
9134   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9135 
9136   Collective
9137 
9138   Input Parameters:
9139 + mat  - the matrix
9140 . row  - row/column permutation
9141 - info - information on desired factorization process
9142 
9143   Level: developer
9144 
9145   Notes:
9146   Probably really in-place only when level of fill is zero, otherwise allocates
9147   new space to store factored matrix and deletes previous memory.
9148 
9149   Most users should employ the `KSP` interface for linear solvers
9150   instead of working directly with matrix algebra routines such as this.
9151   See, e.g., `KSPCreate()`.
9152 
9153   Developer Note:
9154   The Fortran interface is not autogenerated as the
9155   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9156 
9157 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9158 @*/
9159 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9160 {
9161   PetscFunctionBegin;
9162   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9163   PetscValidType(mat, 1);
9164   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9165   PetscAssertPointer(info, 3);
9166   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9167   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9168   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9169   MatCheckPreallocated(mat, 1);
9170   PetscUseTypeMethod(mat, iccfactor, row, info);
9171   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9172   PetscFunctionReturn(PETSC_SUCCESS);
9173 }
9174 
9175 /*@
9176   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9177   ghosted ones.
9178 
9179   Not Collective
9180 
9181   Input Parameters:
9182 + mat  - the matrix
9183 - diag - the diagonal values, including ghost ones
9184 
9185   Level: developer
9186 
9187   Notes:
9188   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9189 
9190   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9191 
9192 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9193 @*/
9194 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9195 {
9196   PetscMPIInt size;
9197 
9198   PetscFunctionBegin;
9199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9200   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9201   PetscValidType(mat, 1);
9202 
9203   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9204   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9205   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9206   if (size == 1) {
9207     PetscInt n, m;
9208     PetscCall(VecGetSize(diag, &n));
9209     PetscCall(MatGetSize(mat, NULL, &m));
9210     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9211     PetscCall(MatDiagonalScale(mat, NULL, diag));
9212   } else {
9213     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9214   }
9215   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9216   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9217   PetscFunctionReturn(PETSC_SUCCESS);
9218 }
9219 
9220 /*@
9221   MatGetInertia - Gets the inertia from a factored matrix
9222 
9223   Collective
9224 
9225   Input Parameter:
9226 . mat - the matrix
9227 
9228   Output Parameters:
9229 + nneg  - number of negative eigenvalues
9230 . nzero - number of zero eigenvalues
9231 - npos  - number of positive eigenvalues
9232 
9233   Level: advanced
9234 
9235   Note:
9236   Matrix must have been factored by `MatCholeskyFactor()`
9237 
9238 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9239 @*/
9240 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9241 {
9242   PetscFunctionBegin;
9243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9244   PetscValidType(mat, 1);
9245   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9246   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9247   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9248   PetscFunctionReturn(PETSC_SUCCESS);
9249 }
9250 
9251 /*@C
9252   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9253 
9254   Neighbor-wise Collective
9255 
9256   Input Parameters:
9257 + mat - the factored matrix obtained with `MatGetFactor()`
9258 - b   - the right-hand-side vectors
9259 
9260   Output Parameter:
9261 . x - the result vectors
9262 
9263   Level: developer
9264 
9265   Note:
9266   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9267   call `MatSolves`(A,x,x).
9268 
9269 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9270 @*/
9271 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9272 {
9273   PetscFunctionBegin;
9274   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9275   PetscValidType(mat, 1);
9276   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9277   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9278   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9279 
9280   MatCheckPreallocated(mat, 1);
9281   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9282   PetscUseTypeMethod(mat, solves, b, x);
9283   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9284   PetscFunctionReturn(PETSC_SUCCESS);
9285 }
9286 
9287 /*@
9288   MatIsSymmetric - Test whether a matrix is symmetric
9289 
9290   Collective
9291 
9292   Input Parameters:
9293 + A   - the matrix to test
9294 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9295 
9296   Output Parameter:
9297 . flg - the result
9298 
9299   Level: intermediate
9300 
9301   Notes:
9302   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9303 
9304   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9305 
9306   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9307   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9308 
9309 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9310           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9311 @*/
9312 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9313 {
9314   PetscFunctionBegin;
9315   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9316   PetscAssertPointer(flg, 3);
9317 
9318   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9319   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9320   else {
9321     PetscUseTypeMethod(A, issymmetric, tol, flg);
9322     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9323   }
9324   PetscFunctionReturn(PETSC_SUCCESS);
9325 }
9326 
9327 /*@
9328   MatIsHermitian - Test whether a matrix is Hermitian
9329 
9330   Collective
9331 
9332   Input Parameters:
9333 + A   - the matrix to test
9334 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9335 
9336   Output Parameter:
9337 . flg - the result
9338 
9339   Level: intermediate
9340 
9341   Notes:
9342   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9343 
9344   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9345 
9346   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9347   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9348 
9349 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9350           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9351 @*/
9352 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9353 {
9354   PetscFunctionBegin;
9355   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9356   PetscAssertPointer(flg, 3);
9357 
9358   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9359   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9360   else {
9361     PetscUseTypeMethod(A, ishermitian, tol, flg);
9362     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9363   }
9364   PetscFunctionReturn(PETSC_SUCCESS);
9365 }
9366 
9367 /*@
9368   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9369 
9370   Not Collective
9371 
9372   Input Parameter:
9373 . A - the matrix to check
9374 
9375   Output Parameters:
9376 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9377 - flg - the result (only valid if set is `PETSC_TRUE`)
9378 
9379   Level: advanced
9380 
9381   Notes:
9382   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9383   if you want it explicitly checked
9384 
9385   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9386   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9387 
9388 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9389 @*/
9390 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9391 {
9392   PetscFunctionBegin;
9393   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9394   PetscAssertPointer(set, 2);
9395   PetscAssertPointer(flg, 3);
9396   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9397     *set = PETSC_TRUE;
9398     *flg = PetscBool3ToBool(A->symmetric);
9399   } else {
9400     *set = PETSC_FALSE;
9401   }
9402   PetscFunctionReturn(PETSC_SUCCESS);
9403 }
9404 
9405 /*@
9406   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9407 
9408   Not Collective
9409 
9410   Input Parameter:
9411 . A - the matrix to check
9412 
9413   Output Parameters:
9414 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9415 - flg - the result (only valid if set is `PETSC_TRUE`)
9416 
9417   Level: advanced
9418 
9419   Notes:
9420   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9421 
9422   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9423   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9424 
9425 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9426 @*/
9427 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9428 {
9429   PetscFunctionBegin;
9430   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9431   PetscAssertPointer(set, 2);
9432   PetscAssertPointer(flg, 3);
9433   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9434     *set = PETSC_TRUE;
9435     *flg = PetscBool3ToBool(A->spd);
9436   } else {
9437     *set = PETSC_FALSE;
9438   }
9439   PetscFunctionReturn(PETSC_SUCCESS);
9440 }
9441 
9442 /*@
9443   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9444 
9445   Not Collective
9446 
9447   Input Parameter:
9448 . A - the matrix to check
9449 
9450   Output Parameters:
9451 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9452 - flg - the result (only valid if set is `PETSC_TRUE`)
9453 
9454   Level: advanced
9455 
9456   Notes:
9457   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9458   if you want it explicitly checked
9459 
9460   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9461   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9462 
9463 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9464 @*/
9465 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9466 {
9467   PetscFunctionBegin;
9468   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9469   PetscAssertPointer(set, 2);
9470   PetscAssertPointer(flg, 3);
9471   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9472     *set = PETSC_TRUE;
9473     *flg = PetscBool3ToBool(A->hermitian);
9474   } else {
9475     *set = PETSC_FALSE;
9476   }
9477   PetscFunctionReturn(PETSC_SUCCESS);
9478 }
9479 
9480 /*@
9481   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9482 
9483   Collective
9484 
9485   Input Parameter:
9486 . A - the matrix to test
9487 
9488   Output Parameter:
9489 . flg - the result
9490 
9491   Level: intermediate
9492 
9493   Notes:
9494   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9495 
9496   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
9497   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9498 
9499 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9500 @*/
9501 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9502 {
9503   PetscFunctionBegin;
9504   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9505   PetscAssertPointer(flg, 2);
9506   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9507     *flg = PetscBool3ToBool(A->structurally_symmetric);
9508   } else {
9509     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9510     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9511   }
9512   PetscFunctionReturn(PETSC_SUCCESS);
9513 }
9514 
9515 /*@
9516   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9517 
9518   Not Collective
9519 
9520   Input Parameter:
9521 . A - the matrix to check
9522 
9523   Output Parameters:
9524 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9525 - flg - the result (only valid if set is PETSC_TRUE)
9526 
9527   Level: advanced
9528 
9529   Notes:
9530   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
9531   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9532 
9533   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9534 
9535 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9536 @*/
9537 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9538 {
9539   PetscFunctionBegin;
9540   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9541   PetscAssertPointer(set, 2);
9542   PetscAssertPointer(flg, 3);
9543   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9544     *set = PETSC_TRUE;
9545     *flg = PetscBool3ToBool(A->structurally_symmetric);
9546   } else {
9547     *set = PETSC_FALSE;
9548   }
9549   PetscFunctionReturn(PETSC_SUCCESS);
9550 }
9551 
9552 /*@
9553   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9554   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9555 
9556   Not Collective
9557 
9558   Input Parameter:
9559 . mat - the matrix
9560 
9561   Output Parameters:
9562 + nstash    - the size of the stash
9563 . reallocs  - the number of additional mallocs incurred.
9564 . bnstash   - the size of the block stash
9565 - breallocs - the number of additional mallocs incurred.in the block stash
9566 
9567   Level: advanced
9568 
9569 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9570 @*/
9571 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9572 {
9573   PetscFunctionBegin;
9574   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9575   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9576   PetscFunctionReturn(PETSC_SUCCESS);
9577 }
9578 
9579 /*@C
9580   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9581   parallel layout, `PetscLayout` for rows and columns
9582 
9583   Collective
9584 
9585   Input Parameter:
9586 . mat - the matrix
9587 
9588   Output Parameters:
9589 + right - (optional) vector that the matrix can be multiplied against
9590 - left  - (optional) vector that the matrix vector product can be stored in
9591 
9592   Level: advanced
9593 
9594   Notes:
9595   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()`.
9596 
9597   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9598 
9599 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9600 @*/
9601 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9602 {
9603   PetscFunctionBegin;
9604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9605   PetscValidType(mat, 1);
9606   if (mat->ops->getvecs) {
9607     PetscUseTypeMethod(mat, getvecs, right, left);
9608   } else {
9609     if (right) {
9610       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9611       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9612       PetscCall(VecSetType(*right, mat->defaultvectype));
9613 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9614       if (mat->boundtocpu && mat->bindingpropagates) {
9615         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9616         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9617       }
9618 #endif
9619     }
9620     if (left) {
9621       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9622       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9623       PetscCall(VecSetType(*left, mat->defaultvectype));
9624 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9625       if (mat->boundtocpu && mat->bindingpropagates) {
9626         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9627         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9628       }
9629 #endif
9630     }
9631   }
9632   PetscFunctionReturn(PETSC_SUCCESS);
9633 }
9634 
9635 /*@C
9636   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9637   with default values.
9638 
9639   Not Collective
9640 
9641   Input Parameter:
9642 . info - the `MatFactorInfo` data structure
9643 
9644   Level: developer
9645 
9646   Notes:
9647   The solvers are generally used through the `KSP` and `PC` objects, for example
9648   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9649 
9650   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9651 
9652   Developer Note:
9653   The Fortran interface is not autogenerated as the
9654   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9655 
9656 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9657 @*/
9658 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9659 {
9660   PetscFunctionBegin;
9661   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9662   PetscFunctionReturn(PETSC_SUCCESS);
9663 }
9664 
9665 /*@
9666   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9667 
9668   Collective
9669 
9670   Input Parameters:
9671 + mat - the factored matrix
9672 - is  - the index set defining the Schur indices (0-based)
9673 
9674   Level: advanced
9675 
9676   Notes:
9677   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9678 
9679   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9680 
9681   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9682 
9683 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9684           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9685 @*/
9686 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9687 {
9688   PetscErrorCode (*f)(Mat, IS);
9689 
9690   PetscFunctionBegin;
9691   PetscValidType(mat, 1);
9692   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9693   PetscValidType(is, 2);
9694   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9695   PetscCheckSameComm(mat, 1, is, 2);
9696   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9697   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9698   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9699   PetscCall(MatDestroy(&mat->schur));
9700   PetscCall((*f)(mat, is));
9701   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9702   PetscFunctionReturn(PETSC_SUCCESS);
9703 }
9704 
9705 /*@
9706   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9707 
9708   Logically Collective
9709 
9710   Input Parameters:
9711 + F      - the factored matrix obtained by calling `MatGetFactor()`
9712 . S      - location where to return the Schur complement, can be `NULL`
9713 - status - the status of the Schur complement matrix, can be `NULL`
9714 
9715   Level: advanced
9716 
9717   Notes:
9718   You must call `MatFactorSetSchurIS()` before calling this routine.
9719 
9720   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9721 
9722   The routine provides a copy of the Schur matrix stored within the solver data structures.
9723   The caller must destroy the object when it is no longer needed.
9724   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9725 
9726   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)
9727 
9728   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9729 
9730   Developer Note:
9731   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9732   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9733 
9734 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9735 @*/
9736 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9737 {
9738   PetscFunctionBegin;
9739   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9740   if (S) PetscAssertPointer(S, 2);
9741   if (status) PetscAssertPointer(status, 3);
9742   if (S) {
9743     PetscErrorCode (*f)(Mat, Mat *);
9744 
9745     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9746     if (f) {
9747       PetscCall((*f)(F, S));
9748     } else {
9749       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9750     }
9751   }
9752   if (status) *status = F->schur_status;
9753   PetscFunctionReturn(PETSC_SUCCESS);
9754 }
9755 
9756 /*@
9757   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9758 
9759   Logically Collective
9760 
9761   Input Parameters:
9762 + F      - the factored matrix obtained by calling `MatGetFactor()`
9763 . S      - location where to return the Schur complement, can be `NULL`
9764 - status - the status of the Schur complement matrix, can be `NULL`
9765 
9766   Level: advanced
9767 
9768   Notes:
9769   You must call `MatFactorSetSchurIS()` before calling this routine.
9770 
9771   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9772 
9773   The routine returns a the Schur Complement stored within the data structures of the solver.
9774 
9775   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9776 
9777   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9778 
9779   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9780 
9781   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9782 
9783 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9784 @*/
9785 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9786 {
9787   PetscFunctionBegin;
9788   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9789   if (S) {
9790     PetscAssertPointer(S, 2);
9791     *S = F->schur;
9792   }
9793   if (status) {
9794     PetscAssertPointer(status, 3);
9795     *status = F->schur_status;
9796   }
9797   PetscFunctionReturn(PETSC_SUCCESS);
9798 }
9799 
9800 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9801 {
9802   Mat S = F->schur;
9803 
9804   PetscFunctionBegin;
9805   switch (F->schur_status) {
9806   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9807   case MAT_FACTOR_SCHUR_INVERTED:
9808     if (S) {
9809       S->ops->solve             = NULL;
9810       S->ops->matsolve          = NULL;
9811       S->ops->solvetranspose    = NULL;
9812       S->ops->matsolvetranspose = NULL;
9813       S->ops->solveadd          = NULL;
9814       S->ops->solvetransposeadd = NULL;
9815       S->factortype             = MAT_FACTOR_NONE;
9816       PetscCall(PetscFree(S->solvertype));
9817     }
9818   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9819     break;
9820   default:
9821     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9822   }
9823   PetscFunctionReturn(PETSC_SUCCESS);
9824 }
9825 
9826 /*@
9827   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9828 
9829   Logically Collective
9830 
9831   Input Parameters:
9832 + F      - the factored matrix obtained by calling `MatGetFactor()`
9833 . S      - location where the Schur complement is stored
9834 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9835 
9836   Level: advanced
9837 
9838 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9839 @*/
9840 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9841 {
9842   PetscFunctionBegin;
9843   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9844   if (S) {
9845     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9846     *S = NULL;
9847   }
9848   F->schur_status = status;
9849   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9850   PetscFunctionReturn(PETSC_SUCCESS);
9851 }
9852 
9853 /*@
9854   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9855 
9856   Logically Collective
9857 
9858   Input Parameters:
9859 + F   - the factored matrix obtained by calling `MatGetFactor()`
9860 . rhs - location where the right hand side of the Schur complement system is stored
9861 - sol - location where the solution of the Schur complement system has to be returned
9862 
9863   Level: advanced
9864 
9865   Notes:
9866   The sizes of the vectors should match the size of the Schur complement
9867 
9868   Must be called after `MatFactorSetSchurIS()`
9869 
9870 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9871 @*/
9872 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9873 {
9874   PetscFunctionBegin;
9875   PetscValidType(F, 1);
9876   PetscValidType(rhs, 2);
9877   PetscValidType(sol, 3);
9878   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9879   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9880   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9881   PetscCheckSameComm(F, 1, rhs, 2);
9882   PetscCheckSameComm(F, 1, sol, 3);
9883   PetscCall(MatFactorFactorizeSchurComplement(F));
9884   switch (F->schur_status) {
9885   case MAT_FACTOR_SCHUR_FACTORED:
9886     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9887     break;
9888   case MAT_FACTOR_SCHUR_INVERTED:
9889     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9890     break;
9891   default:
9892     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9893   }
9894   PetscFunctionReturn(PETSC_SUCCESS);
9895 }
9896 
9897 /*@
9898   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9899 
9900   Logically Collective
9901 
9902   Input Parameters:
9903 + F   - the factored matrix obtained by calling `MatGetFactor()`
9904 . rhs - location where the right hand side of the Schur complement system is stored
9905 - sol - location where the solution of the Schur complement system has to be returned
9906 
9907   Level: advanced
9908 
9909   Notes:
9910   The sizes of the vectors should match the size of the Schur complement
9911 
9912   Must be called after `MatFactorSetSchurIS()`
9913 
9914 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9915 @*/
9916 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9917 {
9918   PetscFunctionBegin;
9919   PetscValidType(F, 1);
9920   PetscValidType(rhs, 2);
9921   PetscValidType(sol, 3);
9922   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9923   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9924   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9925   PetscCheckSameComm(F, 1, rhs, 2);
9926   PetscCheckSameComm(F, 1, sol, 3);
9927   PetscCall(MatFactorFactorizeSchurComplement(F));
9928   switch (F->schur_status) {
9929   case MAT_FACTOR_SCHUR_FACTORED:
9930     PetscCall(MatSolve(F->schur, rhs, sol));
9931     break;
9932   case MAT_FACTOR_SCHUR_INVERTED:
9933     PetscCall(MatMult(F->schur, rhs, sol));
9934     break;
9935   default:
9936     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9937   }
9938   PetscFunctionReturn(PETSC_SUCCESS);
9939 }
9940 
9941 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9942 #if PetscDefined(HAVE_CUDA)
9943 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9944 #endif
9945 
9946 /* Schur status updated in the interface */
9947 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9948 {
9949   Mat S = F->schur;
9950 
9951   PetscFunctionBegin;
9952   if (S) {
9953     PetscMPIInt size;
9954     PetscBool   isdense, isdensecuda;
9955 
9956     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9957     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9958     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9959     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9960     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9961     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9962     if (isdense) {
9963       PetscCall(MatSeqDenseInvertFactors_Private(S));
9964     } else if (isdensecuda) {
9965 #if defined(PETSC_HAVE_CUDA)
9966       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9967 #endif
9968     }
9969     // HIP??????????????
9970     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9971   }
9972   PetscFunctionReturn(PETSC_SUCCESS);
9973 }
9974 
9975 /*@
9976   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9977 
9978   Logically Collective
9979 
9980   Input Parameter:
9981 . F - the factored matrix obtained by calling `MatGetFactor()`
9982 
9983   Level: advanced
9984 
9985   Notes:
9986   Must be called after `MatFactorSetSchurIS()`.
9987 
9988   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9989 
9990 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9991 @*/
9992 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9993 {
9994   PetscFunctionBegin;
9995   PetscValidType(F, 1);
9996   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9997   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9998   PetscCall(MatFactorFactorizeSchurComplement(F));
9999   PetscCall(MatFactorInvertSchurComplement_Private(F));
10000   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10001   PetscFunctionReturn(PETSC_SUCCESS);
10002 }
10003 
10004 /*@
10005   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10006 
10007   Logically Collective
10008 
10009   Input Parameter:
10010 . F - the factored matrix obtained by calling `MatGetFactor()`
10011 
10012   Level: advanced
10013 
10014   Note:
10015   Must be called after `MatFactorSetSchurIS()`
10016 
10017 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10018 @*/
10019 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10020 {
10021   MatFactorInfo info;
10022 
10023   PetscFunctionBegin;
10024   PetscValidType(F, 1);
10025   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10026   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10027   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10028   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10029   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10030     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10031   } else {
10032     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10033   }
10034   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10035   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10036   PetscFunctionReturn(PETSC_SUCCESS);
10037 }
10038 
10039 /*@
10040   MatPtAP - Creates the matrix product $C = P^T * A * P$
10041 
10042   Neighbor-wise Collective
10043 
10044   Input Parameters:
10045 + A     - the matrix
10046 . P     - the projection matrix
10047 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10048 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
10049           if the result is a dense matrix this is irrelevant
10050 
10051   Output Parameter:
10052 . C - the product matrix
10053 
10054   Level: intermediate
10055 
10056   Notes:
10057   C will be created and must be destroyed by the user with `MatDestroy()`.
10058 
10059   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10060 
10061   Developer Note:
10062   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10063 
10064 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10065 @*/
10066 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10067 {
10068   PetscFunctionBegin;
10069   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10070   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10071 
10072   if (scall == MAT_INITIAL_MATRIX) {
10073     PetscCall(MatProductCreate(A, P, NULL, C));
10074     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10075     PetscCall(MatProductSetAlgorithm(*C, "default"));
10076     PetscCall(MatProductSetFill(*C, fill));
10077 
10078     (*C)->product->api_user = PETSC_TRUE;
10079     PetscCall(MatProductSetFromOptions(*C));
10080     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);
10081     PetscCall(MatProductSymbolic(*C));
10082   } else { /* scall == MAT_REUSE_MATRIX */
10083     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10084   }
10085 
10086   PetscCall(MatProductNumeric(*C));
10087   (*C)->symmetric = A->symmetric;
10088   (*C)->spd       = A->spd;
10089   PetscFunctionReturn(PETSC_SUCCESS);
10090 }
10091 
10092 /*@
10093   MatRARt - Creates the matrix product $C = R * A * R^T$
10094 
10095   Neighbor-wise Collective
10096 
10097   Input Parameters:
10098 + A     - the matrix
10099 . R     - the projection matrix
10100 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10101 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
10102           if the result is a dense matrix this is irrelevant
10103 
10104   Output Parameter:
10105 . C - the product matrix
10106 
10107   Level: intermediate
10108 
10109   Notes:
10110   C will be created and must be destroyed by the user with `MatDestroy()`.
10111 
10112   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10113 
10114   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10115   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10116   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
10117   We recommend using MatPtAP().
10118 
10119 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10120 @*/
10121 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10122 {
10123   PetscFunctionBegin;
10124   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10125   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10126 
10127   if (scall == MAT_INITIAL_MATRIX) {
10128     PetscCall(MatProductCreate(A, R, NULL, C));
10129     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10130     PetscCall(MatProductSetAlgorithm(*C, "default"));
10131     PetscCall(MatProductSetFill(*C, fill));
10132 
10133     (*C)->product->api_user = PETSC_TRUE;
10134     PetscCall(MatProductSetFromOptions(*C));
10135     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);
10136     PetscCall(MatProductSymbolic(*C));
10137   } else { /* scall == MAT_REUSE_MATRIX */
10138     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10139   }
10140 
10141   PetscCall(MatProductNumeric(*C));
10142   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10143   PetscFunctionReturn(PETSC_SUCCESS);
10144 }
10145 
10146 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10147 {
10148   PetscBool flg = PETSC_TRUE;
10149 
10150   PetscFunctionBegin;
10151   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10152   if (scall == MAT_INITIAL_MATRIX) {
10153     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10154     PetscCall(MatProductCreate(A, B, NULL, C));
10155     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10156     PetscCall(MatProductSetFill(*C, fill));
10157   } else { /* scall == MAT_REUSE_MATRIX */
10158     Mat_Product *product = (*C)->product;
10159 
10160     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10161     if (flg && product && product->type != ptype) {
10162       PetscCall(MatProductClear(*C));
10163       product = NULL;
10164     }
10165     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10166     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10167       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10168       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10169       product        = (*C)->product;
10170       product->fill  = fill;
10171       product->clear = PETSC_TRUE;
10172     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10173       flg = PETSC_FALSE;
10174       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10175     }
10176   }
10177   if (flg) {
10178     (*C)->product->api_user = PETSC_TRUE;
10179     PetscCall(MatProductSetType(*C, ptype));
10180     PetscCall(MatProductSetFromOptions(*C));
10181     PetscCall(MatProductSymbolic(*C));
10182   }
10183   PetscCall(MatProductNumeric(*C));
10184   PetscFunctionReturn(PETSC_SUCCESS);
10185 }
10186 
10187 /*@
10188   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10189 
10190   Neighbor-wise Collective
10191 
10192   Input Parameters:
10193 + A     - the left matrix
10194 . B     - the right matrix
10195 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10196 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10197           if the result is a dense matrix this is irrelevant
10198 
10199   Output Parameter:
10200 . C - the product matrix
10201 
10202   Notes:
10203   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10204 
10205   `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
10206   call to this function with `MAT_INITIAL_MATRIX`.
10207 
10208   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10209 
10210   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`,
10211   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10212 
10213   Example of Usage:
10214 .vb
10215      MatProductCreate(A,B,NULL,&C);
10216      MatProductSetType(C,MATPRODUCT_AB);
10217      MatProductSymbolic(C);
10218      MatProductNumeric(C); // compute C=A * B
10219      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10220      MatProductNumeric(C);
10221      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10222      MatProductNumeric(C);
10223 .ve
10224 
10225   Level: intermediate
10226 
10227 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10228 @*/
10229 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10230 {
10231   PetscFunctionBegin;
10232   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10233   PetscFunctionReturn(PETSC_SUCCESS);
10234 }
10235 
10236 /*@
10237   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
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_DEFAULT` if not known
10246 
10247   Output Parameter:
10248 . C - the product matrix
10249 
10250   Options Database Key:
10251 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10252               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10253               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10254 
10255   Level: intermediate
10256 
10257   Notes:
10258   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10259 
10260   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10261 
10262   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10263   actually needed.
10264 
10265   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10266   and for pairs of `MATMPIDENSE` matrices.
10267 
10268   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10269 
10270 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10271 @*/
10272 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10273 {
10274   PetscFunctionBegin;
10275   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10276   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10277   PetscFunctionReturn(PETSC_SUCCESS);
10278 }
10279 
10280 /*@
10281   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10282 
10283   Neighbor-wise Collective
10284 
10285   Input Parameters:
10286 + A     - the left matrix
10287 . B     - the right matrix
10288 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10289 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10290 
10291   Output Parameter:
10292 . C - the product matrix
10293 
10294   Level: intermediate
10295 
10296   Notes:
10297   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10298 
10299   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10300 
10301   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10302 
10303   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10304   actually needed.
10305 
10306   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10307   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10308 
10309 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10310 @*/
10311 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10312 {
10313   PetscFunctionBegin;
10314   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10315   PetscFunctionReturn(PETSC_SUCCESS);
10316 }
10317 
10318 /*@
10319   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10320 
10321   Neighbor-wise Collective
10322 
10323   Input Parameters:
10324 + A     - the left matrix
10325 . B     - the middle matrix
10326 . C     - the right matrix
10327 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10328 - fill  - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
10329           if the result is a dense matrix this is irrelevant
10330 
10331   Output Parameter:
10332 . D - the product matrix
10333 
10334   Level: intermediate
10335 
10336   Notes:
10337   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10338 
10339   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10340 
10341   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10342 
10343   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10344   actually needed.
10345 
10346   If you have many matrices with the same non-zero structure to multiply, you
10347   should use `MAT_REUSE_MATRIX` in all calls but the first
10348 
10349 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10350 @*/
10351 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10352 {
10353   PetscFunctionBegin;
10354   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10355   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10356 
10357   if (scall == MAT_INITIAL_MATRIX) {
10358     PetscCall(MatProductCreate(A, B, C, D));
10359     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10360     PetscCall(MatProductSetAlgorithm(*D, "default"));
10361     PetscCall(MatProductSetFill(*D, fill));
10362 
10363     (*D)->product->api_user = PETSC_TRUE;
10364     PetscCall(MatProductSetFromOptions(*D));
10365     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,
10366                ((PetscObject)C)->type_name);
10367     PetscCall(MatProductSymbolic(*D));
10368   } else { /* user may change input matrices when REUSE */
10369     PetscCall(MatProductReplaceMats(A, B, C, *D));
10370   }
10371   PetscCall(MatProductNumeric(*D));
10372   PetscFunctionReturn(PETSC_SUCCESS);
10373 }
10374 
10375 /*@
10376   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10377 
10378   Collective
10379 
10380   Input Parameters:
10381 + mat      - the matrix
10382 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10383 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10384 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10385 
10386   Output Parameter:
10387 . matredundant - redundant matrix
10388 
10389   Level: advanced
10390 
10391   Notes:
10392   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10393   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10394 
10395   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10396   calling it.
10397 
10398   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10399 
10400 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10401 @*/
10402 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10403 {
10404   MPI_Comm       comm;
10405   PetscMPIInt    size;
10406   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10407   Mat_Redundant *redund     = NULL;
10408   PetscSubcomm   psubcomm   = NULL;
10409   MPI_Comm       subcomm_in = subcomm;
10410   Mat           *matseq;
10411   IS             isrow, iscol;
10412   PetscBool      newsubcomm = PETSC_FALSE;
10413 
10414   PetscFunctionBegin;
10415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10416   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10417     PetscAssertPointer(*matredundant, 5);
10418     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10419   }
10420 
10421   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10422   if (size == 1 || nsubcomm == 1) {
10423     if (reuse == MAT_INITIAL_MATRIX) {
10424       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10425     } else {
10426       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");
10427       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10428     }
10429     PetscFunctionReturn(PETSC_SUCCESS);
10430   }
10431 
10432   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10433   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10434   MatCheckPreallocated(mat, 1);
10435 
10436   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10437   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10438     /* create psubcomm, then get subcomm */
10439     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10440     PetscCallMPI(MPI_Comm_size(comm, &size));
10441     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10442 
10443     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10444     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10445     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10446     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10447     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10448     newsubcomm = PETSC_TRUE;
10449     PetscCall(PetscSubcommDestroy(&psubcomm));
10450   }
10451 
10452   /* get isrow, iscol and a local sequential matrix matseq[0] */
10453   if (reuse == MAT_INITIAL_MATRIX) {
10454     mloc_sub = PETSC_DECIDE;
10455     nloc_sub = PETSC_DECIDE;
10456     if (bs < 1) {
10457       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10458       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10459     } else {
10460       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10461       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10462     }
10463     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10464     rstart = rend - mloc_sub;
10465     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10466     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10467     PetscCall(ISSetIdentity(iscol));
10468   } else { /* reuse == MAT_REUSE_MATRIX */
10469     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");
10470     /* retrieve subcomm */
10471     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10472     redund = (*matredundant)->redundant;
10473     isrow  = redund->isrow;
10474     iscol  = redund->iscol;
10475     matseq = redund->matseq;
10476   }
10477   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10478 
10479   /* get matredundant over subcomm */
10480   if (reuse == MAT_INITIAL_MATRIX) {
10481     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10482 
10483     /* create a supporting struct and attach it to C for reuse */
10484     PetscCall(PetscNew(&redund));
10485     (*matredundant)->redundant = redund;
10486     redund->isrow              = isrow;
10487     redund->iscol              = iscol;
10488     redund->matseq             = matseq;
10489     if (newsubcomm) {
10490       redund->subcomm = subcomm;
10491     } else {
10492       redund->subcomm = MPI_COMM_NULL;
10493     }
10494   } else {
10495     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10496   }
10497 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10498   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10499     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10500     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10501   }
10502 #endif
10503   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10504   PetscFunctionReturn(PETSC_SUCCESS);
10505 }
10506 
10507 /*@C
10508   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10509   a given `Mat`. Each submatrix can span multiple procs.
10510 
10511   Collective
10512 
10513   Input Parameters:
10514 + mat     - the matrix
10515 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10516 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10517 
10518   Output Parameter:
10519 . subMat - parallel sub-matrices each spanning a given `subcomm`
10520 
10521   Level: advanced
10522 
10523   Notes:
10524   The submatrix partition across processors is dictated by `subComm` a
10525   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10526   is not restricted to be grouped with consecutive original MPI processes.
10527 
10528   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10529   map directly to the layout of the original matrix [wrt the local
10530   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10531   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10532   the `subMat`. However the offDiagMat looses some columns - and this is
10533   reconstructed with `MatSetValues()`
10534 
10535   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10536 
10537 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10538 @*/
10539 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10540 {
10541   PetscMPIInt commsize, subCommSize;
10542 
10543   PetscFunctionBegin;
10544   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10545   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10546   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10547 
10548   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");
10549   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10550   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10551   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10552   PetscFunctionReturn(PETSC_SUCCESS);
10553 }
10554 
10555 /*@
10556   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10557 
10558   Not Collective
10559 
10560   Input Parameters:
10561 + mat   - matrix to extract local submatrix from
10562 . isrow - local row indices for submatrix
10563 - iscol - local column indices for submatrix
10564 
10565   Output Parameter:
10566 . submat - the submatrix
10567 
10568   Level: intermediate
10569 
10570   Notes:
10571   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10572 
10573   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10574   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10575 
10576   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10577   `MatSetValuesBlockedLocal()` will also be implemented.
10578 
10579   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10580   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10581 
10582 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10583 @*/
10584 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10585 {
10586   PetscFunctionBegin;
10587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10588   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10589   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10590   PetscCheckSameComm(isrow, 2, iscol, 3);
10591   PetscAssertPointer(submat, 4);
10592   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10593 
10594   if (mat->ops->getlocalsubmatrix) {
10595     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10596   } else {
10597     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10598   }
10599   PetscFunctionReturn(PETSC_SUCCESS);
10600 }
10601 
10602 /*@
10603   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10604 
10605   Not Collective
10606 
10607   Input Parameters:
10608 + mat    - matrix to extract local submatrix from
10609 . isrow  - local row indices for submatrix
10610 . iscol  - local column indices for submatrix
10611 - submat - the submatrix
10612 
10613   Level: intermediate
10614 
10615 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10616 @*/
10617 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10618 {
10619   PetscFunctionBegin;
10620   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10621   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10622   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10623   PetscCheckSameComm(isrow, 2, iscol, 3);
10624   PetscAssertPointer(submat, 4);
10625   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10626 
10627   if (mat->ops->restorelocalsubmatrix) {
10628     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10629   } else {
10630     PetscCall(MatDestroy(submat));
10631   }
10632   *submat = NULL;
10633   PetscFunctionReturn(PETSC_SUCCESS);
10634 }
10635 
10636 /*@
10637   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10638 
10639   Collective
10640 
10641   Input Parameter:
10642 . mat - the matrix
10643 
10644   Output Parameter:
10645 . is - if any rows have zero diagonals this contains the list of them
10646 
10647   Level: developer
10648 
10649 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10650 @*/
10651 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10652 {
10653   PetscFunctionBegin;
10654   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10655   PetscValidType(mat, 1);
10656   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10657   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10658 
10659   if (!mat->ops->findzerodiagonals) {
10660     Vec                diag;
10661     const PetscScalar *a;
10662     PetscInt          *rows;
10663     PetscInt           rStart, rEnd, r, nrow = 0;
10664 
10665     PetscCall(MatCreateVecs(mat, &diag, NULL));
10666     PetscCall(MatGetDiagonal(mat, diag));
10667     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10668     PetscCall(VecGetArrayRead(diag, &a));
10669     for (r = 0; r < rEnd - rStart; ++r)
10670       if (a[r] == 0.0) ++nrow;
10671     PetscCall(PetscMalloc1(nrow, &rows));
10672     nrow = 0;
10673     for (r = 0; r < rEnd - rStart; ++r)
10674       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10675     PetscCall(VecRestoreArrayRead(diag, &a));
10676     PetscCall(VecDestroy(&diag));
10677     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10678   } else {
10679     PetscUseTypeMethod(mat, findzerodiagonals, is);
10680   }
10681   PetscFunctionReturn(PETSC_SUCCESS);
10682 }
10683 
10684 /*@
10685   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10686 
10687   Collective
10688 
10689   Input Parameter:
10690 . mat - the matrix
10691 
10692   Output Parameter:
10693 . is - contains the list of rows with off block diagonal entries
10694 
10695   Level: developer
10696 
10697 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10698 @*/
10699 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10700 {
10701   PetscFunctionBegin;
10702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10703   PetscValidType(mat, 1);
10704   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10705   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10706 
10707   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10708   PetscFunctionReturn(PETSC_SUCCESS);
10709 }
10710 
10711 /*@C
10712   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10713 
10714   Collective; No Fortran Support
10715 
10716   Input Parameter:
10717 . mat - the matrix
10718 
10719   Output Parameter:
10720 . values - the block inverses in column major order (FORTRAN-like)
10721 
10722   Level: advanced
10723 
10724   Notes:
10725   The size of the blocks is determined by the block size of the matrix.
10726 
10727   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10728 
10729   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10730 
10731 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10732 @*/
10733 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10734 {
10735   PetscFunctionBegin;
10736   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10737   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10738   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10739   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10740   PetscFunctionReturn(PETSC_SUCCESS);
10741 }
10742 
10743 /*@C
10744   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10745 
10746   Collective; No Fortran Support
10747 
10748   Input Parameters:
10749 + mat     - the matrix
10750 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10751 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10752 
10753   Output Parameter:
10754 . values - the block inverses in column major order (FORTRAN-like)
10755 
10756   Level: advanced
10757 
10758   Notes:
10759   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10760 
10761   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10762 
10763 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10764 @*/
10765 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10766 {
10767   PetscFunctionBegin;
10768   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10769   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10770   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10771   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10772   PetscFunctionReturn(PETSC_SUCCESS);
10773 }
10774 
10775 /*@
10776   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10777 
10778   Collective
10779 
10780   Input Parameters:
10781 + A - the matrix
10782 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10783 
10784   Level: advanced
10785 
10786   Note:
10787   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10788 
10789 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10790 @*/
10791 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10792 {
10793   const PetscScalar *vals;
10794   PetscInt          *dnnz;
10795   PetscInt           m, rstart, rend, bs, i, j;
10796 
10797   PetscFunctionBegin;
10798   PetscCall(MatInvertBlockDiagonal(A, &vals));
10799   PetscCall(MatGetBlockSize(A, &bs));
10800   PetscCall(MatGetLocalSize(A, &m, NULL));
10801   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10802   PetscCall(PetscMalloc1(m / bs, &dnnz));
10803   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10804   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10805   PetscCall(PetscFree(dnnz));
10806   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10807   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10808   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10809   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10810   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10811   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10812   PetscFunctionReturn(PETSC_SUCCESS);
10813 }
10814 
10815 /*@C
10816   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10817   via `MatTransposeColoringCreate()`.
10818 
10819   Collective
10820 
10821   Input Parameter:
10822 . c - coloring context
10823 
10824   Level: intermediate
10825 
10826 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10827 @*/
10828 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10829 {
10830   MatTransposeColoring matcolor = *c;
10831 
10832   PetscFunctionBegin;
10833   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10834   if (--((PetscObject)matcolor)->refct > 0) {
10835     matcolor = NULL;
10836     PetscFunctionReturn(PETSC_SUCCESS);
10837   }
10838 
10839   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10840   PetscCall(PetscFree(matcolor->rows));
10841   PetscCall(PetscFree(matcolor->den2sp));
10842   PetscCall(PetscFree(matcolor->colorforcol));
10843   PetscCall(PetscFree(matcolor->columns));
10844   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10845   PetscCall(PetscHeaderDestroy(c));
10846   PetscFunctionReturn(PETSC_SUCCESS);
10847 }
10848 
10849 /*@C
10850   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10851   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10852   `MatTransposeColoring` to sparse `B`.
10853 
10854   Collective
10855 
10856   Input Parameters:
10857 + coloring - coloring context created with `MatTransposeColoringCreate()`
10858 - B        - sparse matrix
10859 
10860   Output Parameter:
10861 . Btdense - dense matrix $B^T$
10862 
10863   Level: developer
10864 
10865   Note:
10866   These are used internally for some implementations of `MatRARt()`
10867 
10868 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10869 @*/
10870 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10871 {
10872   PetscFunctionBegin;
10873   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10874   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10875   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10876 
10877   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10878   PetscFunctionReturn(PETSC_SUCCESS);
10879 }
10880 
10881 /*@C
10882   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10883   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10884   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10885   $C_{sp}$ from $C_{den}$.
10886 
10887   Collective
10888 
10889   Input Parameters:
10890 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10891 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10892 
10893   Output Parameter:
10894 . Csp - sparse matrix
10895 
10896   Level: developer
10897 
10898   Note:
10899   These are used internally for some implementations of `MatRARt()`
10900 
10901 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10902 @*/
10903 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10904 {
10905   PetscFunctionBegin;
10906   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10907   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10908   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10909 
10910   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10911   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10912   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10913   PetscFunctionReturn(PETSC_SUCCESS);
10914 }
10915 
10916 /*@C
10917   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10918 
10919   Collective
10920 
10921   Input Parameters:
10922 + mat        - the matrix product C
10923 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10924 
10925   Output Parameter:
10926 . color - the new coloring context
10927 
10928   Level: intermediate
10929 
10930 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10931           `MatTransColoringApplyDenToSp()`
10932 @*/
10933 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10934 {
10935   MatTransposeColoring c;
10936   MPI_Comm             comm;
10937 
10938   PetscFunctionBegin;
10939   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10940   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10941   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10942 
10943   c->ctype = iscoloring->ctype;
10944   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10945 
10946   *color = c;
10947   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10948   PetscFunctionReturn(PETSC_SUCCESS);
10949 }
10950 
10951 /*@
10952   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10953   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10954   same, otherwise it will be larger
10955 
10956   Not Collective
10957 
10958   Input Parameter:
10959 . mat - the matrix
10960 
10961   Output Parameter:
10962 . state - the current state
10963 
10964   Level: intermediate
10965 
10966   Notes:
10967   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10968   different matrices
10969 
10970   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10971 
10972   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10973 
10974 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10975 @*/
10976 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10977 {
10978   PetscFunctionBegin;
10979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10980   *state = mat->nonzerostate;
10981   PetscFunctionReturn(PETSC_SUCCESS);
10982 }
10983 
10984 /*@
10985   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10986   matrices from each processor
10987 
10988   Collective
10989 
10990   Input Parameters:
10991 + comm   - the communicators the parallel matrix will live on
10992 . seqmat - the input sequential matrices
10993 . n      - number of local columns (or `PETSC_DECIDE`)
10994 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10995 
10996   Output Parameter:
10997 . mpimat - the parallel matrix generated
10998 
10999   Level: developer
11000 
11001   Note:
11002   The number of columns of the matrix in EACH processor MUST be the same.
11003 
11004 .seealso: [](ch_matrices), `Mat`
11005 @*/
11006 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11007 {
11008   PetscMPIInt size;
11009 
11010   PetscFunctionBegin;
11011   PetscCallMPI(MPI_Comm_size(comm, &size));
11012   if (size == 1) {
11013     if (reuse == MAT_INITIAL_MATRIX) {
11014       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11015     } else {
11016       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11017     }
11018     PetscFunctionReturn(PETSC_SUCCESS);
11019   }
11020 
11021   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");
11022 
11023   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11024   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11025   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11026   PetscFunctionReturn(PETSC_SUCCESS);
11027 }
11028 
11029 /*@
11030   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11031 
11032   Collective
11033 
11034   Input Parameters:
11035 + A - the matrix to create subdomains from
11036 - N - requested number of subdomains
11037 
11038   Output Parameters:
11039 + n   - number of subdomains resulting on this MPI process
11040 - iss - `IS` list with indices of subdomains on this MPI process
11041 
11042   Level: advanced
11043 
11044   Note:
11045   The number of subdomains must be smaller than the communicator size
11046 
11047 .seealso: [](ch_matrices), `Mat`, `IS`
11048 @*/
11049 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11050 {
11051   MPI_Comm    comm, subcomm;
11052   PetscMPIInt size, rank, color;
11053   PetscInt    rstart, rend, k;
11054 
11055   PetscFunctionBegin;
11056   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11057   PetscCallMPI(MPI_Comm_size(comm, &size));
11058   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11059   PetscCheck(N >= 1 && N < (PetscInt)size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N);
11060   *n    = 1;
11061   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11062   color = rank / k;
11063   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11064   PetscCall(PetscMalloc1(1, iss));
11065   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11066   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11067   PetscCallMPI(MPI_Comm_free(&subcomm));
11068   PetscFunctionReturn(PETSC_SUCCESS);
11069 }
11070 
11071 /*@
11072   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11073 
11074   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11075   If they are not the same, uses `MatMatMatMult()`.
11076 
11077   Once the coarse grid problem is constructed, correct for interpolation operators
11078   that are not of full rank, which can legitimately happen in the case of non-nested
11079   geometric multigrid.
11080 
11081   Input Parameters:
11082 + restrct     - restriction operator
11083 . dA          - fine grid matrix
11084 . interpolate - interpolation operator
11085 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11086 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
11087 
11088   Output Parameter:
11089 . A - the Galerkin coarse matrix
11090 
11091   Options Database Key:
11092 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11093 
11094   Level: developer
11095 
11096 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11097 @*/
11098 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11099 {
11100   IS  zerorows;
11101   Vec diag;
11102 
11103   PetscFunctionBegin;
11104   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11105   /* Construct the coarse grid matrix */
11106   if (interpolate == restrct) {
11107     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11108   } else {
11109     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11110   }
11111 
11112   /* If the interpolation matrix is not of full rank, A will have zero rows.
11113      This can legitimately happen in the case of non-nested geometric multigrid.
11114      In that event, we set the rows of the matrix to the rows of the identity,
11115      ignoring the equations (as the RHS will also be zero). */
11116 
11117   PetscCall(MatFindZeroRows(*A, &zerorows));
11118 
11119   if (zerorows != NULL) { /* if there are any zero rows */
11120     PetscCall(MatCreateVecs(*A, &diag, NULL));
11121     PetscCall(MatGetDiagonal(*A, diag));
11122     PetscCall(VecISSet(diag, zerorows, 1.0));
11123     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11124     PetscCall(VecDestroy(&diag));
11125     PetscCall(ISDestroy(&zerorows));
11126   }
11127   PetscFunctionReturn(PETSC_SUCCESS);
11128 }
11129 
11130 /*@C
11131   MatSetOperation - Allows user to set a matrix operation for any matrix type
11132 
11133   Logically Collective
11134 
11135   Input Parameters:
11136 + mat - the matrix
11137 . op  - the name of the operation
11138 - f   - the function that provides the operation
11139 
11140   Level: developer
11141 
11142   Example Usage:
11143 .vb
11144   extern PetscErrorCode usermult(Mat, Vec, Vec);
11145 
11146   PetscCall(MatCreateXXX(comm, ..., &A));
11147   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11148 .ve
11149 
11150   Notes:
11151   See the file `include/petscmat.h` for a complete list of matrix
11152   operations, which all have the form MATOP_<OPERATION>, where
11153   <OPERATION> is the name (in all capital letters) of the
11154   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11155 
11156   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11157   sequence as the usual matrix interface routines, since they
11158   are intended to be accessed via the usual matrix interface
11159   routines, e.g.,
11160 .vb
11161   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11162 .ve
11163 
11164   In particular each function MUST return `PETSC_SUCCESS` on success and
11165   nonzero on failure.
11166 
11167   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11168 
11169 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11170 @*/
11171 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11172 {
11173   PetscFunctionBegin;
11174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11175   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11176   (((void (**)(void))mat->ops)[op]) = f;
11177   PetscFunctionReturn(PETSC_SUCCESS);
11178 }
11179 
11180 /*@C
11181   MatGetOperation - Gets a matrix operation for any matrix type.
11182 
11183   Not Collective
11184 
11185   Input Parameters:
11186 + mat - the matrix
11187 - op  - the name of the operation
11188 
11189   Output Parameter:
11190 . f - the function that provides the operation
11191 
11192   Level: developer
11193 
11194   Example Usage:
11195 .vb
11196   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11197 
11198   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11199 .ve
11200 
11201   Notes:
11202   See the file include/petscmat.h for a complete list of matrix
11203   operations, which all have the form MATOP_<OPERATION>, where
11204   <OPERATION> is the name (in all capital letters) of the
11205   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11206 
11207   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11208 
11209 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11210 @*/
11211 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11212 {
11213   PetscFunctionBegin;
11214   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11215   *f = (((void (**)(void))mat->ops)[op]);
11216   PetscFunctionReturn(PETSC_SUCCESS);
11217 }
11218 
11219 /*@
11220   MatHasOperation - Determines whether the given matrix supports the particular operation.
11221 
11222   Not Collective
11223 
11224   Input Parameters:
11225 + mat - the matrix
11226 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11227 
11228   Output Parameter:
11229 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11230 
11231   Level: advanced
11232 
11233   Note:
11234   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11235 
11236 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11237 @*/
11238 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11239 {
11240   PetscFunctionBegin;
11241   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11242   PetscAssertPointer(has, 3);
11243   if (mat->ops->hasoperation) {
11244     PetscUseTypeMethod(mat, hasoperation, op, has);
11245   } else {
11246     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11247     else {
11248       *has = PETSC_FALSE;
11249       if (op == MATOP_CREATE_SUBMATRIX) {
11250         PetscMPIInt size;
11251 
11252         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11253         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11254       }
11255     }
11256   }
11257   PetscFunctionReturn(PETSC_SUCCESS);
11258 }
11259 
11260 /*@
11261   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11262 
11263   Collective
11264 
11265   Input Parameter:
11266 . mat - the matrix
11267 
11268   Output Parameter:
11269 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11270 
11271   Level: beginner
11272 
11273 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11274 @*/
11275 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11276 {
11277   PetscFunctionBegin;
11278   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11279   PetscValidType(mat, 1);
11280   PetscAssertPointer(cong, 2);
11281   if (!mat->rmap || !mat->cmap) {
11282     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11283     PetscFunctionReturn(PETSC_SUCCESS);
11284   }
11285   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11286     PetscCall(PetscLayoutSetUp(mat->rmap));
11287     PetscCall(PetscLayoutSetUp(mat->cmap));
11288     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11289     if (*cong) mat->congruentlayouts = 1;
11290     else mat->congruentlayouts = 0;
11291   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11292   PetscFunctionReturn(PETSC_SUCCESS);
11293 }
11294 
11295 PetscErrorCode MatSetInf(Mat A)
11296 {
11297   PetscFunctionBegin;
11298   PetscUseTypeMethod(A, setinf);
11299   PetscFunctionReturn(PETSC_SUCCESS);
11300 }
11301 
11302 /*@C
11303   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
11304   and possibly removes small values from the graph structure.
11305 
11306   Collective
11307 
11308   Input Parameters:
11309 + A       - the matrix
11310 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11311 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11312 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11313 . num_idx - size of 'index' array
11314 - index   - array of block indices to use for graph strength of connection weight
11315 
11316   Output Parameter:
11317 . graph - the resulting graph
11318 
11319   Level: advanced
11320 
11321 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11322 @*/
11323 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11324 {
11325   PetscFunctionBegin;
11326   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11327   PetscValidType(A, 1);
11328   PetscValidLogicalCollectiveBool(A, scale, 3);
11329   PetscAssertPointer(graph, 7);
11330   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11331   PetscFunctionReturn(PETSC_SUCCESS);
11332 }
11333 
11334 /*@
11335   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11336   meaning the same memory is used for the matrix, and no new memory is allocated.
11337 
11338   Collective
11339 
11340   Input Parameters:
11341 + A    - the matrix
11342 - 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
11343 
11344   Level: intermediate
11345 
11346   Developer Note:
11347   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11348   of the arrays in the data structure are unneeded.
11349 
11350 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11351 @*/
11352 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11353 {
11354   PetscFunctionBegin;
11355   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11356   PetscUseTypeMethod(A, eliminatezeros, keep);
11357   PetscFunctionReturn(PETSC_SUCCESS);
11358 }
11359