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