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