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