xref: /petsc/src/mat/interface/matrix.c (revision c87776d362bbdcf41177f47d22f77862065f4f4d)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51   MatSetRandom - Sets all components of a matrix to random numbers.
52 
53   Logically Collective
54 
55   Input Parameters:
56 + x    - the matrix
57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60   Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67   Level: intermediate
68 
69   Notes:
70   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
71 
72   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
73 
74   It generates an error if used on unassembled sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109   Logically Collective
110 
111   Input Parameter:
112 . mat - the factored matrix
113 
114   Output Parameters:
115 + pivot - the pivot value computed
116 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119   Level: advanced
120 
121   Notes:
122   This routine does not work for factorizations done with external packages.
123 
124   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
130 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
149 . mat - the factored matrix
150 
151   Output Parameter:
152 . err - the error code
153 
154   Level: advanced
155 
156   Note:
157   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172   MatFactorClearError - clears the error code in a factorization
173 
174   Logically Collective
175 
176   Input Parameter:
177 . mat - the factored matrix
178 
179   Level: developer
180 
181   Note:
182   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n, st;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
207     PetscCall(MatGetSize(mat, &N, NULL));
208     PetscCall(MatGetLocalSize(mat, &n, NULL));
209     PetscCall(VecSet(l, 0.0));
210     PetscCall(VecSetRandom(r, NULL));
211     PetscCall(MatMult(mat, r, l));
212     PetscCall(VecGetArrayRead(l, &al));
213   } else { /* nonzero columns */
214     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
215     PetscCall(MatGetSize(mat, NULL, &N));
216     PetscCall(MatGetLocalSize(mat, NULL, &n));
217     PetscCall(VecSet(r, 0.0));
218     PetscCall(VecSetRandom(l, NULL));
219     PetscCall(MatMultTranspose(mat, l, r));
220     PetscCall(VecGetArrayRead(r, &al));
221   }
222   if (tol <= 0.0) {
223     for (i = 0, nz = 0; i < n; i++)
224       if (al[i] != 0.0) nz++;
225   } else {
226     for (i = 0, nz = 0; i < n; i++)
227       if (PetscAbsScalar(al[i]) > tol) nz++;
228   }
229   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
230   if (gnz != N) {
231     PetscInt *nzr;
232     PetscCall(PetscMalloc1(nz, &nzr));
233     if (nz) {
234       if (tol < 0) {
235         for (i = 0, nz = 0; i < n; i++)
236           if (al[i] != 0.0) nzr[nz++] = i + st;
237       } else {
238         for (i = 0, nz = 0; i < n; i++)
239           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
240       }
241     }
242     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
243   } else *nonzero = NULL;
244   if (!cols) { /* nonzero rows */
245     PetscCall(VecRestoreArrayRead(l, &al));
246   } else {
247     PetscCall(VecRestoreArrayRead(r, &al));
248   }
249   PetscCall(VecDestroy(&l));
250   PetscCall(VecDestroy(&r));
251   PetscFunctionReturn(PETSC_SUCCESS);
252 }
253 
254 /*@
255   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
256 
257   Input Parameter:
258 . mat - the matrix
259 
260   Output Parameter:
261 . keptrows - the rows that are not completely zero
262 
263   Level: intermediate
264 
265   Note:
266   `keptrows` is set to `NULL` if all rows are nonzero.
267 
268 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
269  @*/
270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
271 {
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
274   PetscValidType(mat, 1);
275   PetscAssertPointer(keptrows, 2);
276   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
277   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
278   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
279   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
280   PetscFunctionReturn(PETSC_SUCCESS);
281 }
282 
283 /*@
284   MatFindZeroRows - Locate all rows that are completely zero in the matrix
285 
286   Input Parameter:
287 . mat - the matrix
288 
289   Output Parameter:
290 . zerorows - the rows that are completely zero
291 
292   Level: intermediate
293 
294   Note:
295   `zerorows` is set to `NULL` if no rows are zero.
296 
297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
298  @*/
299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
300 {
301   IS       keptrows;
302   PetscInt m, n;
303 
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
306   PetscValidType(mat, 1);
307   PetscAssertPointer(zerorows, 2);
308   PetscCall(MatFindNonzeroRows(mat, &keptrows));
309   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
310      In keeping with this convention, we set zerorows to NULL if there are no zero
311      rows. */
312   if (keptrows == NULL) {
313     *zerorows = NULL;
314   } else {
315     PetscCall(MatGetOwnershipRange(mat, &m, &n));
316     PetscCall(ISComplement(keptrows, m, n, zerorows));
317     PetscCall(ISDestroy(&keptrows));
318   }
319   PetscFunctionReturn(PETSC_SUCCESS);
320 }
321 
322 /*@
323   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
324 
325   Not Collective
326 
327   Input Parameter:
328 . A - the matrix
329 
330   Output Parameter:
331 . a - the diagonal part (which is a SEQUENTIAL matrix)
332 
333   Level: advanced
334 
335   Notes:
336   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
337 
338   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
339 
340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
341 @*/
342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
343 {
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
346   PetscValidType(A, 1);
347   PetscAssertPointer(a, 2);
348   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
349   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
350   else {
351     PetscMPIInt size;
352 
353     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
354     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
355     *a = A;
356   }
357   PetscFunctionReturn(PETSC_SUCCESS);
358 }
359 
360 /*@
361   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
362 
363   Collective
364 
365   Input Parameter:
366 . mat - the matrix
367 
368   Output Parameter:
369 . trace - the sum of the diagonal entries
370 
371   Level: advanced
372 
373 .seealso: [](ch_matrices), `Mat`
374 @*/
375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
376 {
377   Vec diag;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
381   PetscAssertPointer(trace, 2);
382   PetscCall(MatCreateVecs(mat, &diag, NULL));
383   PetscCall(MatGetDiagonal(mat, diag));
384   PetscCall(VecSum(diag, trace));
385   PetscCall(VecDestroy(&diag));
386   PetscFunctionReturn(PETSC_SUCCESS);
387 }
388 
389 /*@
390   MatRealPart - Zeros out the imaginary part of the matrix
391 
392   Logically Collective
393 
394   Input Parameter:
395 . mat - the matrix
396 
397   Level: advanced
398 
399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
400 @*/
401 PetscErrorCode MatRealPart(Mat mat)
402 {
403   PetscFunctionBegin;
404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
405   PetscValidType(mat, 1);
406   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
407   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
408   MatCheckPreallocated(mat, 1);
409   PetscUseTypeMethod(mat, realpart);
410   PetscFunctionReturn(PETSC_SUCCESS);
411 }
412 
413 /*@C
414   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
415 
416   Collective
417 
418   Input Parameter:
419 . mat - the matrix
420 
421   Output Parameters:
422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
423 - ghosts  - the global indices of the ghost points
424 
425   Level: advanced
426 
427   Note:
428   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
429 
430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
431 @*/
432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
433 {
434   PetscFunctionBegin;
435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
436   PetscValidType(mat, 1);
437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
439   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
440   else {
441     if (nghosts) *nghosts = 0;
442     if (ghosts) *ghosts = NULL;
443   }
444   PetscFunctionReturn(PETSC_SUCCESS);
445 }
446 
447 /*@
448   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
449 
450   Logically Collective
451 
452   Input Parameter:
453 . mat - the matrix
454 
455   Level: advanced
456 
457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
458 @*/
459 PetscErrorCode MatImaginaryPart(Mat mat)
460 {
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
463   PetscValidType(mat, 1);
464   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
465   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
466   MatCheckPreallocated(mat, 1);
467   PetscUseTypeMethod(mat, imaginarypart);
468   PetscFunctionReturn(PETSC_SUCCESS);
469 }
470 
471 /*@
472   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
473 
474   Not Collective
475 
476   Input Parameter:
477 . mat - the matrix
478 
479   Output Parameters:
480 + missing - is any diagonal entry missing
481 - dd      - first diagonal entry that is missing (optional) on this process
482 
483   Level: advanced
484 
485   Note:
486   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
487 
488 .seealso: [](ch_matrices), `Mat`
489 @*/
490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
491 {
492   PetscFunctionBegin;
493   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
494   PetscValidType(mat, 1);
495   PetscAssertPointer(missing, 2);
496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
498   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
499   PetscFunctionReturn(PETSC_SUCCESS);
500 }
501 
502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
503 /*@C
504   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
505   for each row that you get to ensure that your application does
506   not bleed memory.
507 
508   Not Collective
509 
510   Input Parameters:
511 + mat - the matrix
512 - row - the row to get
513 
514   Output Parameters:
515 + ncols - if not `NULL`, the number of nonzeros in `row`
516 . cols  - if not `NULL`, the column numbers
517 - vals  - if not `NULL`, the numerical values
518 
519   Level: advanced
520 
521   Notes:
522   This routine is provided for people who need to have direct access
523   to the structure of a matrix.  We hope that we provide enough
524   high-level matrix routines that few users will need it.
525 
526   `MatGetRow()` always returns 0-based column indices, regardless of
527   whether the internal representation is 0-based (default) or 1-based.
528 
529   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
530   not wish to extract these quantities.
531 
532   The user can only examine the values extracted with `MatGetRow()`;
533   the values CANNOT be altered.  To change the matrix entries, one
534   must use `MatSetValues()`.
535 
536   You can only have one call to `MatGetRow()` outstanding for a particular
537   matrix at a time, per processor. `MatGetRow()` can only obtain rows
538   associated with the given processor, it cannot get rows from the
539   other processors; for that we suggest using `MatCreateSubMatrices()`, then
540   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
541   is in the global number of rows.
542 
543   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
544 
545   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
546 
547   Fortran Note:
548   The calling sequence is
549 .vb
550    MatGetRow(matrix,row,ncols,cols,values,ierr)
551          Mat     matrix (input)
552          integer row    (input)
553          integer ncols  (output)
554          integer cols(maxcols) (output)
555          double precision (or double complex) values(maxcols) output
556 .ve
557   where maxcols >= maximum nonzeros in any row of the matrix.
558 
559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
560 @*/
561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
562 {
563   PetscInt incols;
564 
565   PetscFunctionBegin;
566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
567   PetscValidType(mat, 1);
568   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
569   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
570   MatCheckPreallocated(mat, 1);
571   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
572   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
573   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
574   if (ncols) *ncols = incols;
575   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
576   PetscFunctionReturn(PETSC_SUCCESS);
577 }
578 
579 /*@
580   MatConjugate - replaces the matrix values with their complex conjugates
581 
582   Logically Collective
583 
584   Input Parameter:
585 . mat - the matrix
586 
587   Level: advanced
588 
589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
590 @*/
591 PetscErrorCode MatConjugate(Mat mat)
592 {
593   PetscFunctionBegin;
594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
596   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
597     PetscUseTypeMethod(mat, conjugate);
598     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
599   }
600   PetscFunctionReturn(PETSC_SUCCESS);
601 }
602 
603 /*@C
604   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
605 
606   Not Collective
607 
608   Input Parameters:
609 + mat   - the matrix
610 . row   - the row to get
611 . ncols - the number of nonzeros
612 . cols  - the columns of the nonzeros
613 - vals  - if nonzero the column values
614 
615   Level: advanced
616 
617   Notes:
618   This routine should be called after you have finished examining the entries.
619 
620   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
621   us of the array after it has been restored. If you pass `NULL`, it will
622   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
623 
624   Fortran Notes:
625   The calling sequence is
626 .vb
627    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
628       Mat     matrix (input)
629       integer row    (input)
630       integer ncols  (output)
631       integer cols(maxcols) (output)
632       double precision (or double complex) values(maxcols) output
633 .ve
634   Where maxcols >= maximum nonzeros in any row of the matrix.
635 
636   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
637   before another call to `MatGetRow()` can be made.
638 
639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
640 @*/
641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
642 {
643   PetscFunctionBegin;
644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
645   if (ncols) PetscAssertPointer(ncols, 3);
646   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
647   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
648   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
649   if (ncols) *ncols = 0;
650   if (cols) *cols = NULL;
651   if (vals) *vals = NULL;
652   PetscFunctionReturn(PETSC_SUCCESS);
653 }
654 
655 /*@
656   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
657   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
658 
659   Not Collective
660 
661   Input Parameter:
662 . mat - the matrix
663 
664   Level: advanced
665 
666   Note:
667   The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
668 
669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
670 @*/
671 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
672 {
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
675   PetscValidType(mat, 1);
676   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
677   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
678   MatCheckPreallocated(mat, 1);
679   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
680   PetscUseTypeMethod(mat, getrowuppertriangular);
681   PetscFunctionReturn(PETSC_SUCCESS);
682 }
683 
684 /*@
685   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
686 
687   Not Collective
688 
689   Input Parameter:
690 . mat - the matrix
691 
692   Level: advanced
693 
694   Note:
695   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
696 
697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
698 @*/
699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
700 {
701   PetscFunctionBegin;
702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
703   PetscValidType(mat, 1);
704   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
705   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
706   MatCheckPreallocated(mat, 1);
707   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
708   PetscUseTypeMethod(mat, restorerowuppertriangular);
709   PetscFunctionReturn(PETSC_SUCCESS);
710 }
711 
712 /*@C
713   MatSetOptionsPrefix - Sets the prefix used for searching for all
714   `Mat` options in the database.
715 
716   Logically Collective
717 
718   Input Parameters:
719 + A      - the matrix
720 - prefix - the prefix to prepend to all option names
721 
722   Level: advanced
723 
724   Notes:
725   A hyphen (-) must NOT be given at the beginning of the prefix name.
726   The first character of all runtime options is AUTOMATICALLY the hyphen.
727 
728   This is NOT used for options for the factorization of the matrix. Normally the
729   prefix is automatically passed in from the PC calling the factorization. To set
730   it directly use  `MatSetOptionsPrefixFactor()`
731 
732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
733 @*/
734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
735 {
736   PetscFunctionBegin;
737   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
738   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
739   PetscFunctionReturn(PETSC_SUCCESS);
740 }
741 
742 /*@C
743   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
744   for matrices created with `MatGetFactor()`
745 
746   Logically Collective
747 
748   Input Parameters:
749 + A      - the matrix
750 - prefix - the prefix to prepend to all option names for the factored matrix
751 
752   Level: developer
753 
754   Notes:
755   A hyphen (-) must NOT be given at the beginning of the prefix name.
756   The first character of all runtime options is AUTOMATICALLY the hyphen.
757 
758   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
759   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
760 
761 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
762 @*/
763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
764 {
765   PetscFunctionBegin;
766   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
767   if (prefix) {
768     PetscAssertPointer(prefix, 2);
769     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
770     if (prefix != A->factorprefix) {
771       PetscCall(PetscFree(A->factorprefix));
772       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
773     }
774   } else PetscCall(PetscFree(A->factorprefix));
775   PetscFunctionReturn(PETSC_SUCCESS);
776 }
777 
778 /*@C
779   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
780   for matrices created with `MatGetFactor()`
781 
782   Logically Collective
783 
784   Input Parameters:
785 + A      - the matrix
786 - prefix - the prefix to prepend to all option names for the factored matrix
787 
788   Level: developer
789 
790   Notes:
791   A hyphen (-) must NOT be given at the beginning of the prefix name.
792   The first character of all runtime options is AUTOMATICALLY the hyphen.
793 
794   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
795   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
796 
797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
798           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
799           `MatSetOptionsPrefix()`
800 @*/
801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
802 {
803   size_t len1, len2, new_len;
804 
805   PetscFunctionBegin;
806   PetscValidHeader(A, 1);
807   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
808   if (!A->factorprefix) {
809     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
810     PetscFunctionReturn(PETSC_SUCCESS);
811   }
812   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
813 
814   PetscCall(PetscStrlen(A->factorprefix, &len1));
815   PetscCall(PetscStrlen(prefix, &len2));
816   new_len = len1 + len2 + 1;
817   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
818   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
819   PetscFunctionReturn(PETSC_SUCCESS);
820 }
821 
822 /*@C
823   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
824   matrix options in the database.
825 
826   Logically Collective
827 
828   Input Parameters:
829 + A      - the matrix
830 - prefix - the prefix to prepend to all option names
831 
832   Level: advanced
833 
834   Note:
835   A hyphen (-) must NOT be given at the beginning of the prefix name.
836   The first character of all runtime options is AUTOMATICALLY the hyphen.
837 
838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
839 @*/
840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
841 {
842   PetscFunctionBegin;
843   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
844   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
845   PetscFunctionReturn(PETSC_SUCCESS);
846 }
847 
848 /*@C
849   MatGetOptionsPrefix - Gets the prefix used for searching for all
850   matrix options in the database.
851 
852   Not Collective
853 
854   Input Parameter:
855 . A - the matrix
856 
857   Output Parameter:
858 . prefix - pointer to the prefix string used
859 
860   Level: advanced
861 
862   Fortran Note:
863   The user should pass in a string `prefix` of
864   sufficient length to hold the prefix.
865 
866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
867 @*/
868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
869 {
870   PetscFunctionBegin;
871   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
872   PetscAssertPointer(prefix, 2);
873   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
874   PetscFunctionReturn(PETSC_SUCCESS);
875 }
876 
877 /*@
878   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
879 
880   Collective
881 
882   Input Parameter:
883 . A - the matrix
884 
885   Level: beginner
886 
887   Notes:
888   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
889 
890   Users can reset the preallocation to access the original memory.
891 
892   Currently only supported for  `MATAIJ` matrices.
893 
894 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
895 @*/
896 PetscErrorCode MatResetPreallocation(Mat A)
897 {
898   PetscFunctionBegin;
899   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
900   PetscValidType(A, 1);
901   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
902   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
903   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
904   PetscFunctionReturn(PETSC_SUCCESS);
905 }
906 
907 /*@
908   MatSetUp - Sets up the internal matrix data structures for later use.
909 
910   Collective
911 
912   Input Parameter:
913 . A - the matrix
914 
915   Level: intermediate
916 
917   Notes:
918   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
919   setting values in the matrix.
920 
921   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
922 
923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
924 @*/
925 PetscErrorCode MatSetUp(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   if (!((PetscObject)A)->type_name) {
930     PetscMPIInt size;
931 
932     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
933     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
934   }
935   if (!A->preallocated) PetscTryTypeMethod(A, setup);
936   PetscCall(PetscLayoutSetUp(A->rmap));
937   PetscCall(PetscLayoutSetUp(A->cmap));
938   A->preallocated = PETSC_TRUE;
939   PetscFunctionReturn(PETSC_SUCCESS);
940 }
941 
942 #if defined(PETSC_HAVE_SAWS)
943   #include <petscviewersaws.h>
944 #endif
945 
946 /*
947    If threadsafety is on extraneous matrices may be printed
948 
949    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
950 */
951 #if !defined(PETSC_HAVE_THREADSAFETY)
952 static PetscInt insidematview = 0;
953 #endif
954 
955 /*@C
956   MatViewFromOptions - View properties of the matrix based on options set in the options database
957 
958   Collective
959 
960   Input Parameters:
961 + A    - the matrix
962 . obj  - optional additional object that provides the options prefix to use
963 - name - command line option
964 
965   Options Database Key:
966 . -mat_view [viewertype]:... - the viewer and its options
967 
968   Level: intermediate
969 
970   Note:
971 .vb
972     If no value is provided ascii:stdout is used
973        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
974                                                   for example ascii::ascii_info prints just the information about the object not all details
975                                                   unless :append is given filename opens in write mode, overwriting what was already there
976        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
977        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
978        socket[:port]                             defaults to the standard output port
979        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
980 .ve
981 
982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
983 @*/
984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
985 {
986   PetscFunctionBegin;
987   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
988 #if !defined(PETSC_HAVE_THREADSAFETY)
989   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
990 #endif
991   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
992   PetscFunctionReturn(PETSC_SUCCESS);
993 }
994 
995 /*@C
996   MatView - display information about a matrix in a variety ways
997 
998   Collective
999 
1000   Input Parameters:
1001 + mat    - the matrix
1002 - viewer - visualization context
1003 
1004   Options Database Keys:
1005 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1006 . -mat_view ::ascii_info_detail    - Prints more detailed info
1007 . -mat_view                        - Prints matrix in ASCII format
1008 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1009 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1010 . -display <name>                  - Sets display name (default is host)
1011 . -draw_pause <sec>                - Sets number of seconds to pause after display
1012 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1013 . -viewer_socket_machine <machine> - -
1014 . -viewer_socket_port <port>       - -
1015 . -mat_view binary                 - save matrix to file in binary format
1016 - -viewer_binary_filename <name>   - -
1017 
1018   Level: beginner
1019 
1020   Notes:
1021   The available visualization contexts include
1022 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1023 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1024 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1025 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1026 
1027   The user can open alternative visualization contexts with
1028 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1029 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1030   specified file; corresponding input uses `MatLoad()`
1031 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1032   an X window display
1033 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1034   Currently only the `MATSEQDENSE` and `MATAIJ`
1035   matrix types support the Socket viewer.
1036 
1037   The user can call `PetscViewerPushFormat()` to specify the output
1038   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1039   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1040 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1041 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1042 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1043 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1044   format common among all matrix types
1045 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1046   format (which is in many cases the same as the default)
1047 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1048   size and structure (not the matrix entries)
1049 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1050   the matrix structure
1051 
1052   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1053   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1054 
1055   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1056 
1057   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1058   viewer is used.
1059 
1060   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1061   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1062 
1063   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1064   and then use the following mouse functions.
1065 .vb
1066   left mouse: zoom in
1067   middle mouse: zoom out
1068   right mouse: continue with the simulation
1069 .ve
1070 
1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1072           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1073 @*/
1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1075 {
1076   PetscInt          rows, cols, rbs, cbs;
1077   PetscBool         isascii, isstring, issaws;
1078   PetscViewerFormat format;
1079   PetscMPIInt       size;
1080 
1081   PetscFunctionBegin;
1082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1083   PetscValidType(mat, 1);
1084   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1085   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1086   PetscCheckSameComm(mat, 1, viewer, 2);
1087 
1088   PetscCall(PetscViewerGetFormat(viewer, &format));
1089   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1090   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1091 
1092 #if !defined(PETSC_HAVE_THREADSAFETY)
1093   insidematview++;
1094 #endif
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1097   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1098   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1099 
1100   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1101   if (isascii) {
1102     if (!mat->preallocated) {
1103       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1104 #if !defined(PETSC_HAVE_THREADSAFETY)
1105       insidematview--;
1106 #endif
1107       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1108       PetscFunctionReturn(PETSC_SUCCESS);
1109     }
1110     if (!mat->assembled) {
1111       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1112 #if !defined(PETSC_HAVE_THREADSAFETY)
1113       insidematview--;
1114 #endif
1115       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1116       PetscFunctionReturn(PETSC_SUCCESS);
1117     }
1118     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1119     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1120       MatNullSpace nullsp, transnullsp;
1121 
1122       PetscCall(PetscViewerASCIIPushTab(viewer));
1123       PetscCall(MatGetSize(mat, &rows, &cols));
1124       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1125       if (rbs != 1 || cbs != 1) {
1126         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1127         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1128       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1129       if (mat->factortype) {
1130         MatSolverType solver;
1131         PetscCall(MatFactorGetSolverType(mat, &solver));
1132         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1133       }
1134       if (mat->ops->getinfo) {
1135         MatInfo info;
1136         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1137         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1138         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1139       }
1140       PetscCall(MatGetNullSpace(mat, &nullsp));
1141       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1142       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1143       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1144       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1145       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1146       PetscCall(PetscViewerASCIIPushTab(viewer));
1147       PetscCall(MatProductView(mat, viewer));
1148       PetscCall(PetscViewerASCIIPopTab(viewer));
1149     }
1150   } else if (issaws) {
1151 #if defined(PETSC_HAVE_SAWS)
1152     PetscMPIInt rank;
1153 
1154     PetscCall(PetscObjectName((PetscObject)mat));
1155     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1156     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1157 #endif
1158   } else if (isstring) {
1159     const char *type;
1160     PetscCall(MatGetType(mat, &type));
1161     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1162     PetscTryTypeMethod(mat, view, viewer);
1163   }
1164   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1165     PetscCall(PetscViewerASCIIPushTab(viewer));
1166     PetscUseTypeMethod(mat, viewnative, viewer);
1167     PetscCall(PetscViewerASCIIPopTab(viewer));
1168   } else if (mat->ops->view) {
1169     PetscCall(PetscViewerASCIIPushTab(viewer));
1170     PetscUseTypeMethod(mat, view, viewer);
1171     PetscCall(PetscViewerASCIIPopTab(viewer));
1172   }
1173   if (isascii) {
1174     PetscCall(PetscViewerGetFormat(viewer, &format));
1175     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1176   }
1177   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1178 #if !defined(PETSC_HAVE_THREADSAFETY)
1179   insidematview--;
1180 #endif
1181   PetscFunctionReturn(PETSC_SUCCESS);
1182 }
1183 
1184 #if defined(PETSC_USE_DEBUG)
1185   #include <../src/sys/totalview/tv_data_display.h>
1186 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1187 {
1188   TV_add_row("Local rows", "int", &mat->rmap->n);
1189   TV_add_row("Local columns", "int", &mat->cmap->n);
1190   TV_add_row("Global rows", "int", &mat->rmap->N);
1191   TV_add_row("Global columns", "int", &mat->cmap->N);
1192   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1193   return TV_format_OK;
1194 }
1195 #endif
1196 
1197 /*@C
1198   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1199   with `MatView()`.  The matrix format is determined from the options database.
1200   Generates a parallel MPI matrix if the communicator has more than one
1201   processor.  The default matrix type is `MATAIJ`.
1202 
1203   Collective
1204 
1205   Input Parameters:
1206 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1207             or some related function before a call to `MatLoad()`
1208 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1209 
1210   Options Database Key:
1211 . -matload_block_size <bs> - set block size
1212 
1213   Level: beginner
1214 
1215   Notes:
1216   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1217   `Mat` before calling this routine if you wish to set it from the options database.
1218 
1219   `MatLoad()` automatically loads into the options database any options
1220   given in the file filename.info where filename is the name of the file
1221   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1222   file will be ignored if you use the -viewer_binary_skip_info option.
1223 
1224   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1225   sets the default matrix type AIJ and sets the local and global sizes.
1226   If type and/or size is already set, then the same are used.
1227 
1228   In parallel, each processor can load a subset of rows (or the
1229   entire matrix).  This routine is especially useful when a large
1230   matrix is stored on disk and only part of it is desired on each
1231   processor.  For example, a parallel solver may access only some of
1232   the rows from each processor.  The algorithm used here reads
1233   relatively small blocks of data rather than reading the entire
1234   matrix and then subsetting it.
1235 
1236   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1237   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1238   or the sequence like
1239 .vb
1240     `PetscViewer` v;
1241     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1242     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1243     `PetscViewerSetFromOptions`(v);
1244     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1245     `PetscViewerFileSetName`(v,"datafile");
1246 .ve
1247   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1248 $ -viewer_type {binary, hdf5}
1249 
1250   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1251   and src/mat/tutorials/ex10.c with the second approach.
1252 
1253   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1254   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1255   Multiple objects, both matrices and vectors, can be stored within the same file.
1256   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1257 
1258   Most users should not need to know the details of the binary storage
1259   format, since `MatLoad()` and `MatView()` completely hide these details.
1260   But for anyone who is interested, the standard binary matrix storage
1261   format is
1262 
1263 .vb
1264     PetscInt    MAT_FILE_CLASSID
1265     PetscInt    number of rows
1266     PetscInt    number of columns
1267     PetscInt    total number of nonzeros
1268     PetscInt    *number nonzeros in each row
1269     PetscInt    *column indices of all nonzeros (starting index is zero)
1270     PetscScalar *values of all nonzeros
1271 .ve
1272   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1273   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
1274   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1275 
1276   PETSc automatically does the byte swapping for
1277   machines that store the bytes reversed. Thus if you write your own binary
1278   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1279   and `PetscBinaryWrite()` to see how this may be done.
1280 
1281   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1282   Each processor's chunk is loaded independently by its owning MPI process.
1283   Multiple objects, both matrices and vectors, can be stored within the same file.
1284   They are looked up by their PetscObject name.
1285 
1286   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1287   by default the same structure and naming of the AIJ arrays and column count
1288   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1289 $    save example.mat A b -v7.3
1290   can be directly read by this routine (see Reference 1 for details).
1291 
1292   Depending on your MATLAB version, this format might be a default,
1293   otherwise you can set it as default in Preferences.
1294 
1295   Unless -nocompression flag is used to save the file in MATLAB,
1296   PETSc must be configured with ZLIB package.
1297 
1298   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1299 
1300   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1301 
1302   Corresponding `MatView()` is not yet implemented.
1303 
1304   The loaded matrix is actually a transpose of the original one in MATLAB,
1305   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1306   With this format, matrix is automatically transposed by PETSc,
1307   unless the matrix is marked as SPD or symmetric
1308   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1309 
1310   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1311 
1312 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1313  @*/
1314 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1315 {
1316   PetscBool flg;
1317 
1318   PetscFunctionBegin;
1319   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1320   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1321 
1322   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1323 
1324   flg = PETSC_FALSE;
1325   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1326   if (flg) {
1327     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1328     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1329   }
1330   flg = PETSC_FALSE;
1331   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1332   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1333 
1334   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1335   PetscUseTypeMethod(mat, load, viewer);
1336   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1337   PetscFunctionReturn(PETSC_SUCCESS);
1338 }
1339 
1340 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1341 {
1342   Mat_Redundant *redund = *redundant;
1343 
1344   PetscFunctionBegin;
1345   if (redund) {
1346     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1347       PetscCall(ISDestroy(&redund->isrow));
1348       PetscCall(ISDestroy(&redund->iscol));
1349       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1350     } else {
1351       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1352       PetscCall(PetscFree(redund->sbuf_j));
1353       PetscCall(PetscFree(redund->sbuf_a));
1354       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1355         PetscCall(PetscFree(redund->rbuf_j[i]));
1356         PetscCall(PetscFree(redund->rbuf_a[i]));
1357       }
1358       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1359     }
1360 
1361     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1362     PetscCall(PetscFree(redund));
1363   }
1364   PetscFunctionReturn(PETSC_SUCCESS);
1365 }
1366 
1367 /*@C
1368   MatDestroy - Frees space taken by a matrix.
1369 
1370   Collective
1371 
1372   Input Parameter:
1373 . A - the matrix
1374 
1375   Level: beginner
1376 
1377   Developer Note:
1378   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1379   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1380   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1381   if changes are needed here.
1382 
1383 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1384 @*/
1385 PetscErrorCode MatDestroy(Mat *A)
1386 {
1387   PetscFunctionBegin;
1388   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1389   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1390   if (--((PetscObject)(*A))->refct > 0) {
1391     *A = NULL;
1392     PetscFunctionReturn(PETSC_SUCCESS);
1393   }
1394 
1395   /* if memory was published with SAWs then destroy it */
1396   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1397   PetscTryTypeMethod((*A), destroy);
1398 
1399   PetscCall(PetscFree((*A)->factorprefix));
1400   PetscCall(PetscFree((*A)->defaultvectype));
1401   PetscCall(PetscFree((*A)->defaultrandtype));
1402   PetscCall(PetscFree((*A)->bsizes));
1403   PetscCall(PetscFree((*A)->solvertype));
1404   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1405   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1406   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1407   PetscCall(MatProductClear(*A));
1408   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1409   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1410   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1411   PetscCall(MatDestroy(&(*A)->schur));
1412   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1413   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1414   PetscCall(PetscHeaderDestroy(A));
1415   PetscFunctionReturn(PETSC_SUCCESS);
1416 }
1417 
1418 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1419 /*@C
1420   MatSetValues - Inserts or adds a block of values into a matrix.
1421   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1422   MUST be called after all calls to `MatSetValues()` have been completed.
1423 
1424   Not Collective
1425 
1426   Input Parameters:
1427 + mat  - the matrix
1428 . v    - a logically two-dimensional array of values
1429 . m    - the number of rows
1430 . idxm - the global indices of the rows
1431 . n    - the number of columns
1432 . idxn - the global indices of the columns
1433 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1434 
1435   Level: beginner
1436 
1437   Notes:
1438   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1439 
1440   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1441   options cannot be mixed without intervening calls to the assembly
1442   routines.
1443 
1444   `MatSetValues()` uses 0-based row and column numbers in Fortran
1445   as well as in C.
1446 
1447   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1448   simply ignored. This allows easily inserting element stiffness matrices
1449   with homogeneous Dirichlet boundary conditions that you don't want represented
1450   in the matrix.
1451 
1452   Efficiency Alert:
1453   The routine `MatSetValuesBlocked()` may offer much better efficiency
1454   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1455 
1456   Developer Note:
1457   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1458   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1459 
1460 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1461           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1462 @*/
1463 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1464 {
1465   PetscFunctionBeginHot;
1466   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1467   PetscValidType(mat, 1);
1468   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1469   PetscAssertPointer(idxm, 3);
1470   PetscAssertPointer(idxn, 5);
1471   MatCheckPreallocated(mat, 1);
1472 
1473   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1474   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1475 
1476   if (PetscDefined(USE_DEBUG)) {
1477     PetscInt i, j;
1478 
1479     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1480     for (i = 0; i < m; i++) {
1481       for (j = 0; j < n; j++) {
1482         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1483 #if defined(PETSC_USE_COMPLEX)
1484           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]);
1485 #else
1486           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]);
1487 #endif
1488       }
1489     }
1490     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);
1491     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);
1492   }
1493 
1494   if (mat->assembled) {
1495     mat->was_assembled = PETSC_TRUE;
1496     mat->assembled     = PETSC_FALSE;
1497   }
1498   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1499   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1500   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1501   PetscFunctionReturn(PETSC_SUCCESS);
1502 }
1503 
1504 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1505 /*@C
1506   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1507   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1508   MUST be called after all calls to `MatSetValues()` have been completed.
1509 
1510   Not Collective
1511 
1512   Input Parameters:
1513 + mat  - the matrix
1514 . v    - a logically two-dimensional array of values
1515 . ism  - the rows to provide
1516 . isn  - the columns to provide
1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519   Level: beginner
1520 
1521   Notes:
1522   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1523 
1524   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525   options cannot be mixed without intervening calls to the assembly
1526   routines.
1527 
1528   `MatSetValues()` uses 0-based row and column numbers in Fortran
1529   as well as in C.
1530 
1531   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1532   simply ignored. This allows easily inserting element stiffness matrices
1533   with homogeneous Dirichlet boundary conditions that you don't want represented
1534   in the matrix.
1535 
1536   Efficiency Alert:
1537   The routine `MatSetValuesBlocked()` may offer much better efficiency
1538   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540   This is currently not optimized for any particular `ISType`
1541 
1542   Developer Note:
1543   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1544   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1545 
1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1547           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1548 @*/
1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1550 {
1551   PetscInt        m, n;
1552   const PetscInt *rows, *cols;
1553 
1554   PetscFunctionBeginHot;
1555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1556   PetscCall(ISGetIndices(ism, &rows));
1557   PetscCall(ISGetIndices(isn, &cols));
1558   PetscCall(ISGetLocalSize(ism, &m));
1559   PetscCall(ISGetLocalSize(isn, &n));
1560   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1561   PetscCall(ISRestoreIndices(ism, &rows));
1562   PetscCall(ISRestoreIndices(isn, &cols));
1563   PetscFunctionReturn(PETSC_SUCCESS);
1564 }
1565 
1566 /*@
1567   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1568   values into a matrix
1569 
1570   Not Collective
1571 
1572   Input Parameters:
1573 + mat - the matrix
1574 . row - the (block) row to set
1575 - v   - a logically two-dimensional array of values
1576 
1577   Level: intermediate
1578 
1579   Notes:
1580   The values, `v`, are column-oriented (for the block version) and sorted
1581 
1582   All the nonzero values in `row` must be provided
1583 
1584   The matrix must have previously had its column indices set, likely by having been assembled.
1585 
1586   `row` must belong to this MPI process
1587 
1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1589           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1590 @*/
1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1592 {
1593   PetscInt globalrow;
1594 
1595   PetscFunctionBegin;
1596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1597   PetscValidType(mat, 1);
1598   PetscAssertPointer(v, 3);
1599   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1600   PetscCall(MatSetValuesRow(mat, globalrow, v));
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 /*@
1605   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1606   values into a matrix
1607 
1608   Not Collective
1609 
1610   Input Parameters:
1611 + mat - the matrix
1612 . row - the (block) row to set
1613 - 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
1614 
1615   Level: advanced
1616 
1617   Notes:
1618   The values, `v`, are column-oriented for the block version.
1619 
1620   All the nonzeros in `row` must be provided
1621 
1622   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1623 
1624   `row` must belong to this process
1625 
1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1627           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1628 @*/
1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1630 {
1631   PetscFunctionBeginHot;
1632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1633   PetscValidType(mat, 1);
1634   MatCheckPreallocated(mat, 1);
1635   PetscAssertPointer(v, 3);
1636   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1637   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1638   mat->insertmode = INSERT_VALUES;
1639 
1640   if (mat->assembled) {
1641     mat->was_assembled = PETSC_TRUE;
1642     mat->assembled     = PETSC_FALSE;
1643   }
1644   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1645   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1646   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1647   PetscFunctionReturn(PETSC_SUCCESS);
1648 }
1649 
1650 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1651 /*@
1652   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1653   Using structured grid indexing
1654 
1655   Not Collective
1656 
1657   Input Parameters:
1658 + mat  - the matrix
1659 . m    - number of rows being entered
1660 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1661 . n    - number of columns being entered
1662 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1663 . v    - a logically two-dimensional array of values
1664 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1665 
1666   Level: beginner
1667 
1668   Notes:
1669   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1670 
1671   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1672   options cannot be mixed without intervening calls to the assembly
1673   routines.
1674 
1675   The grid coordinates are across the entire grid, not just the local portion
1676 
1677   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1678   as well as in C.
1679 
1680   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1681 
1682   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1683   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1684 
1685   The columns and rows in the stencil passed in MUST be contained within the
1686   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1687   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1688   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1689   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1690 
1691   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1692   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1693   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1694   `DM_BOUNDARY_PERIODIC` boundary type.
1695 
1696   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
1697   a single value per point) you can skip filling those indices.
1698 
1699   Inspired by the structured grid interface to the HYPRE package
1700   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1701 
1702   Efficiency Alert:
1703   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1704   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1705 
1706   Fortran Note:
1707   `idxm` and `idxn` should be declared as
1708 $     MatStencil idxm(4,m),idxn(4,n)
1709   and the values inserted using
1710 .vb
1711     idxm(MatStencil_i,1) = i
1712     idxm(MatStencil_j,1) = j
1713     idxm(MatStencil_k,1) = k
1714     idxm(MatStencil_c,1) = c
1715     etc
1716 .ve
1717 
1718 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1719           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1720 @*/
1721 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1722 {
1723   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1724   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1725   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1726 
1727   PetscFunctionBegin;
1728   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1730   PetscValidType(mat, 1);
1731   PetscAssertPointer(idxm, 3);
1732   PetscAssertPointer(idxn, 5);
1733 
1734   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1735     jdxm = buf;
1736     jdxn = buf + m;
1737   } else {
1738     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1739     jdxm = bufm;
1740     jdxn = bufn;
1741   }
1742   for (i = 0; i < m; i++) {
1743     for (j = 0; j < 3 - sdim; j++) dxm++;
1744     tmp = *dxm++ - starts[0];
1745     for (j = 0; j < dim - 1; j++) {
1746       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1747       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1748     }
1749     if (mat->stencil.noc) dxm++;
1750     jdxm[i] = tmp;
1751   }
1752   for (i = 0; i < n; i++) {
1753     for (j = 0; j < 3 - sdim; j++) dxn++;
1754     tmp = *dxn++ - starts[0];
1755     for (j = 0; j < dim - 1; j++) {
1756       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1757       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1758     }
1759     if (mat->stencil.noc) dxn++;
1760     jdxn[i] = tmp;
1761   }
1762   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1763   PetscCall(PetscFree2(bufm, bufn));
1764   PetscFunctionReturn(PETSC_SUCCESS);
1765 }
1766 
1767 /*@
1768   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1769   Using structured grid indexing
1770 
1771   Not Collective
1772 
1773   Input Parameters:
1774 + mat  - the matrix
1775 . m    - number of rows being entered
1776 . idxm - grid coordinates for matrix rows being entered
1777 . n    - number of columns being entered
1778 . idxn - grid coordinates for matrix columns being entered
1779 . v    - a logically two-dimensional array of values
1780 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1781 
1782   Level: beginner
1783 
1784   Notes:
1785   By default the values, `v`, are row-oriented and unsorted.
1786   See `MatSetOption()` for other options.
1787 
1788   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1789   options cannot be mixed without intervening calls to the assembly
1790   routines.
1791 
1792   The grid coordinates are across the entire grid, not just the local portion
1793 
1794   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1795   as well as in C.
1796 
1797   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1798 
1799   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1800   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1801 
1802   The columns and rows in the stencil passed in MUST be contained within the
1803   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1804   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1805   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1806   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1807 
1808   Negative indices may be passed in idxm and idxn, these rows and columns are
1809   simply ignored. This allows easily inserting element stiffness matrices
1810   with homogeneous Dirichlet boundary conditions that you don't want represented
1811   in the matrix.
1812 
1813   Inspired by the structured grid interface to the HYPRE package
1814   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1815 
1816   Fortran Note:
1817   `idxm` and `idxn` should be declared as
1818 $     MatStencil idxm(4,m),idxn(4,n)
1819   and the values inserted using
1820 .vb
1821     idxm(MatStencil_i,1) = i
1822     idxm(MatStencil_j,1) = j
1823     idxm(MatStencil_k,1) = k
1824    etc
1825 .ve
1826 
1827 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1828           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1829           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1830 @*/
1831 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1832 {
1833   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1834   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1835   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1836 
1837   PetscFunctionBegin;
1838   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1839   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1840   PetscValidType(mat, 1);
1841   PetscAssertPointer(idxm, 3);
1842   PetscAssertPointer(idxn, 5);
1843   PetscAssertPointer(v, 6);
1844 
1845   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1846     jdxm = buf;
1847     jdxn = buf + m;
1848   } else {
1849     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1850     jdxm = bufm;
1851     jdxn = bufn;
1852   }
1853   for (i = 0; i < m; i++) {
1854     for (j = 0; j < 3 - sdim; j++) dxm++;
1855     tmp = *dxm++ - starts[0];
1856     for (j = 0; j < sdim - 1; j++) {
1857       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1858       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1859     }
1860     dxm++;
1861     jdxm[i] = tmp;
1862   }
1863   for (i = 0; i < n; i++) {
1864     for (j = 0; j < 3 - sdim; j++) dxn++;
1865     tmp = *dxn++ - starts[0];
1866     for (j = 0; j < sdim - 1; j++) {
1867       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1868       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1869     }
1870     dxn++;
1871     jdxn[i] = tmp;
1872   }
1873   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1874   PetscCall(PetscFree2(bufm, bufn));
1875   PetscFunctionReturn(PETSC_SUCCESS);
1876 }
1877 
1878 /*@
1879   MatSetStencil - Sets the grid information for setting values into a matrix via
1880   `MatSetValuesStencil()`
1881 
1882   Not Collective
1883 
1884   Input Parameters:
1885 + mat    - the matrix
1886 . dim    - dimension of the grid 1, 2, or 3
1887 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1888 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1889 - dof    - number of degrees of freedom per node
1890 
1891   Level: beginner
1892 
1893   Notes:
1894   Inspired by the structured grid interface to the HYPRE package
1895   (www.llnl.gov/CASC/hyper)
1896 
1897   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1898   user.
1899 
1900 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1901           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1902 @*/
1903 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1904 {
1905   PetscFunctionBegin;
1906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1907   PetscAssertPointer(dims, 3);
1908   PetscAssertPointer(starts, 4);
1909 
1910   mat->stencil.dim = dim + (dof > 1);
1911   for (PetscInt i = 0; i < dim; i++) {
1912     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1913     mat->stencil.starts[i] = starts[dim - i - 1];
1914   }
1915   mat->stencil.dims[dim]   = dof;
1916   mat->stencil.starts[dim] = 0;
1917   mat->stencil.noc         = (PetscBool)(dof == 1);
1918   PetscFunctionReturn(PETSC_SUCCESS);
1919 }
1920 
1921 /*@C
1922   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1923 
1924   Not Collective
1925 
1926   Input Parameters:
1927 + mat  - the matrix
1928 . v    - a logically two-dimensional array of values
1929 . m    - the number of block rows
1930 . idxm - the global block indices
1931 . n    - the number of block columns
1932 . idxn - the global block indices
1933 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1934 
1935   Level: intermediate
1936 
1937   Notes:
1938   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1939   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1940 
1941   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1942   NOT the total number of rows/columns; for example, if the block size is 2 and
1943   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1944   The values in idxm would be 1 2; that is the first index for each block divided by
1945   the block size.
1946 
1947   You must call `MatSetBlockSize()` when constructing this matrix (before
1948   preallocating it).
1949 
1950   By default the values, `v`, are row-oriented, so the layout of
1951   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1952 
1953   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1954   options cannot be mixed without intervening calls to the assembly
1955   routines.
1956 
1957   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1958   as well as in C.
1959 
1960   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1961   simply ignored. This allows easily inserting element stiffness matrices
1962   with homogeneous Dirichlet boundary conditions that you don't want represented
1963   in the matrix.
1964 
1965   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1966   internal searching must be done to determine where to place the
1967   data in the matrix storage space.  By instead inserting blocks of
1968   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1969   reduced.
1970 
1971   Example:
1972 .vb
1973    Suppose m=n=2 and block size(bs) = 2 The array is
1974 
1975    1  2  | 3  4
1976    5  6  | 7  8
1977    - - - | - - -
1978    9  10 | 11 12
1979    13 14 | 15 16
1980 
1981    v[] should be passed in like
1982    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1983 
1984   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1985    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1986 .ve
1987 
1988 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1989 @*/
1990 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1991 {
1992   PetscFunctionBeginHot;
1993   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1994   PetscValidType(mat, 1);
1995   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1996   PetscAssertPointer(idxm, 3);
1997   PetscAssertPointer(idxn, 5);
1998   MatCheckPreallocated(mat, 1);
1999   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2000   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2001   if (PetscDefined(USE_DEBUG)) {
2002     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2003     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2004   }
2005   if (PetscDefined(USE_DEBUG)) {
2006     PetscInt rbs, cbs, M, N, i;
2007     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2008     PetscCall(MatGetSize(mat, &M, &N));
2009     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
2010     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
2011   }
2012   if (mat->assembled) {
2013     mat->was_assembled = PETSC_TRUE;
2014     mat->assembled     = PETSC_FALSE;
2015   }
2016   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2017   if (mat->ops->setvaluesblocked) {
2018     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2019   } else {
2020     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2021     PetscInt i, j, bs, cbs;
2022 
2023     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2024     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2025       iidxm = buf;
2026       iidxn = buf + m * bs;
2027     } else {
2028       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2029       iidxm = bufr;
2030       iidxn = bufc;
2031     }
2032     for (i = 0; i < m; i++) {
2033       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2034     }
2035     if (m != n || bs != cbs || idxm != idxn) {
2036       for (i = 0; i < n; i++) {
2037         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2038       }
2039     } else iidxn = iidxm;
2040     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2041     PetscCall(PetscFree2(bufr, bufc));
2042   }
2043   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2044   PetscFunctionReturn(PETSC_SUCCESS);
2045 }
2046 
2047 /*@C
2048   MatGetValues - Gets a block of local values from a matrix.
2049 
2050   Not Collective; can only return values that are owned by the give process
2051 
2052   Input Parameters:
2053 + mat  - the matrix
2054 . v    - a logically two-dimensional array for storing the values
2055 . m    - the number of rows
2056 . idxm - the  global indices of the rows
2057 . n    - the number of columns
2058 - idxn - the global indices of the columns
2059 
2060   Level: advanced
2061 
2062   Notes:
2063   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2064   The values, `v`, are then returned in a row-oriented format,
2065   analogous to that used by default in `MatSetValues()`.
2066 
2067   `MatGetValues()` uses 0-based row and column numbers in
2068   Fortran as well as in C.
2069 
2070   `MatGetValues()` requires that the matrix has been assembled
2071   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2072   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2073   without intermediate matrix assembly.
2074 
2075   Negative row or column indices will be ignored and those locations in `v` will be
2076   left unchanged.
2077 
2078   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2079   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2080   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2081 
2082 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2083 @*/
2084 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2085 {
2086   PetscFunctionBegin;
2087   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2088   PetscValidType(mat, 1);
2089   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2090   PetscAssertPointer(idxm, 3);
2091   PetscAssertPointer(idxn, 5);
2092   PetscAssertPointer(v, 6);
2093   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2094   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2095   MatCheckPreallocated(mat, 1);
2096 
2097   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2098   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2099   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2100   PetscFunctionReturn(PETSC_SUCCESS);
2101 }
2102 
2103 /*@C
2104   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2105   defined previously by `MatSetLocalToGlobalMapping()`
2106 
2107   Not Collective
2108 
2109   Input Parameters:
2110 + mat  - the matrix
2111 . nrow - number of rows
2112 . irow - the row local indices
2113 . ncol - number of columns
2114 - icol - the column local indices
2115 
2116   Output Parameter:
2117 . y - a logically two-dimensional array of values
2118 
2119   Level: advanced
2120 
2121   Notes:
2122   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2123 
2124   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,
2125   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2126   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2127   with `MatSetLocalToGlobalMapping()`.
2128 
2129   Developer Note:
2130   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2131   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2132 
2133 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2134           `MatSetValuesLocal()`, `MatGetValues()`
2135 @*/
2136 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2137 {
2138   PetscFunctionBeginHot;
2139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2140   PetscValidType(mat, 1);
2141   MatCheckPreallocated(mat, 1);
2142   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2143   PetscAssertPointer(irow, 3);
2144   PetscAssertPointer(icol, 5);
2145   if (PetscDefined(USE_DEBUG)) {
2146     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2147     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2148   }
2149   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2150   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2151   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2152   else {
2153     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2154     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2155       irowm = buf;
2156       icolm = buf + nrow;
2157     } else {
2158       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2159       irowm = bufr;
2160       icolm = bufc;
2161     }
2162     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2163     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2164     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2165     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2166     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2167     PetscCall(PetscFree2(bufr, bufc));
2168   }
2169   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2170   PetscFunctionReturn(PETSC_SUCCESS);
2171 }
2172 
2173 /*@
2174   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2175   the same size. Currently, this can only be called once and creates the given matrix.
2176 
2177   Not Collective
2178 
2179   Input Parameters:
2180 + mat  - the matrix
2181 . nb   - the number of blocks
2182 . bs   - the number of rows (and columns) in each block
2183 . rows - a concatenation of the rows for each block
2184 - v    - a concatenation of logically two-dimensional arrays of values
2185 
2186   Level: advanced
2187 
2188   Notes:
2189   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2190 
2191   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2192 
2193 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2194           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2195 @*/
2196 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2197 {
2198   PetscFunctionBegin;
2199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2200   PetscValidType(mat, 1);
2201   PetscAssertPointer(rows, 4);
2202   PetscAssertPointer(v, 5);
2203   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2204 
2205   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2206   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2207   else {
2208     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2209   }
2210   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2211   PetscFunctionReturn(PETSC_SUCCESS);
2212 }
2213 
2214 /*@
2215   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2216   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2217   using a local (per-processor) numbering.
2218 
2219   Not Collective
2220 
2221   Input Parameters:
2222 + x        - the matrix
2223 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2224 - cmapping - column mapping
2225 
2226   Level: intermediate
2227 
2228   Note:
2229   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2230 
2231 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2232 @*/
2233 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2234 {
2235   PetscFunctionBegin;
2236   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2237   PetscValidType(x, 1);
2238   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2239   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2240   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2241   else {
2242     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2243     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2244   }
2245   PetscFunctionReturn(PETSC_SUCCESS);
2246 }
2247 
2248 /*@
2249   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2250 
2251   Not Collective
2252 
2253   Input Parameter:
2254 . A - the matrix
2255 
2256   Output Parameters:
2257 + rmapping - row mapping
2258 - cmapping - column mapping
2259 
2260   Level: advanced
2261 
2262 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2263 @*/
2264 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2265 {
2266   PetscFunctionBegin;
2267   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2268   PetscValidType(A, 1);
2269   if (rmapping) {
2270     PetscAssertPointer(rmapping, 2);
2271     *rmapping = A->rmap->mapping;
2272   }
2273   if (cmapping) {
2274     PetscAssertPointer(cmapping, 3);
2275     *cmapping = A->cmap->mapping;
2276   }
2277   PetscFunctionReturn(PETSC_SUCCESS);
2278 }
2279 
2280 /*@
2281   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2282 
2283   Logically Collective
2284 
2285   Input Parameters:
2286 + A    - the matrix
2287 . rmap - row layout
2288 - cmap - column layout
2289 
2290   Level: advanced
2291 
2292   Note:
2293   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2294 
2295 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2296 @*/
2297 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2298 {
2299   PetscFunctionBegin;
2300   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2301   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2302   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2303   PetscFunctionReturn(PETSC_SUCCESS);
2304 }
2305 
2306 /*@
2307   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2308 
2309   Not Collective
2310 
2311   Input Parameter:
2312 . A - the matrix
2313 
2314   Output Parameters:
2315 + rmap - row layout
2316 - cmap - column layout
2317 
2318   Level: advanced
2319 
2320 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2321 @*/
2322 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2323 {
2324   PetscFunctionBegin;
2325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2326   PetscValidType(A, 1);
2327   if (rmap) {
2328     PetscAssertPointer(rmap, 2);
2329     *rmap = A->rmap;
2330   }
2331   if (cmap) {
2332     PetscAssertPointer(cmap, 3);
2333     *cmap = A->cmap;
2334   }
2335   PetscFunctionReturn(PETSC_SUCCESS);
2336 }
2337 
2338 /*@C
2339   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2340   using a local numbering of the rows and columns.
2341 
2342   Not Collective
2343 
2344   Input Parameters:
2345 + mat  - the matrix
2346 . nrow - number of rows
2347 . irow - the row local indices
2348 . ncol - number of columns
2349 . icol - the column local indices
2350 . y    - a logically two-dimensional array of values
2351 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2352 
2353   Level: intermediate
2354 
2355   Notes:
2356   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2357 
2358   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2359   options cannot be mixed without intervening calls to the assembly
2360   routines.
2361 
2362   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2363   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2364 
2365   Developer Note:
2366   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2367   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2368 
2369 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2370           `MatGetValuesLocal()`
2371 @*/
2372 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2373 {
2374   PetscFunctionBeginHot;
2375   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2376   PetscValidType(mat, 1);
2377   MatCheckPreallocated(mat, 1);
2378   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2379   PetscAssertPointer(irow, 3);
2380   PetscAssertPointer(icol, 5);
2381   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2382   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2383   if (PetscDefined(USE_DEBUG)) {
2384     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2385     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2386   }
2387 
2388   if (mat->assembled) {
2389     mat->was_assembled = PETSC_TRUE;
2390     mat->assembled     = PETSC_FALSE;
2391   }
2392   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2393   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2394   else {
2395     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2396     const PetscInt *irowm, *icolm;
2397 
2398     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2399       bufr  = buf;
2400       bufc  = buf + nrow;
2401       irowm = bufr;
2402       icolm = bufc;
2403     } else {
2404       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2405       irowm = bufr;
2406       icolm = bufc;
2407     }
2408     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2409     else irowm = irow;
2410     if (mat->cmap->mapping) {
2411       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2412         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2413       } else icolm = irowm;
2414     } else icolm = icol;
2415     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2416     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2417   }
2418   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2419   PetscFunctionReturn(PETSC_SUCCESS);
2420 }
2421 
2422 /*@C
2423   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2424   using a local ordering of the nodes a block at a time.
2425 
2426   Not Collective
2427 
2428   Input Parameters:
2429 + mat  - the matrix
2430 . nrow - number of rows
2431 . irow - the row local indices
2432 . ncol - number of columns
2433 . icol - the column local indices
2434 . y    - a logically two-dimensional array of values
2435 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2436 
2437   Level: intermediate
2438 
2439   Notes:
2440   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2441   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2442 
2443   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2444   options cannot be mixed without intervening calls to the assembly
2445   routines.
2446 
2447   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2448   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2449 
2450   Developer Note:
2451   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2452   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2453 
2454 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2455           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2456 @*/
2457 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2458 {
2459   PetscFunctionBeginHot;
2460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2461   PetscValidType(mat, 1);
2462   MatCheckPreallocated(mat, 1);
2463   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2464   PetscAssertPointer(irow, 3);
2465   PetscAssertPointer(icol, 5);
2466   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2467   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2468   if (PetscDefined(USE_DEBUG)) {
2469     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2470     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);
2471   }
2472 
2473   if (mat->assembled) {
2474     mat->was_assembled = PETSC_TRUE;
2475     mat->assembled     = PETSC_FALSE;
2476   }
2477   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2478     PetscInt irbs, rbs;
2479     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2480     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2481     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2482   }
2483   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2484     PetscInt icbs, cbs;
2485     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2486     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2487     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2488   }
2489   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2490   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2491   else {
2492     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2493     const PetscInt *irowm, *icolm;
2494 
2495     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2496       bufr  = buf;
2497       bufc  = buf + nrow;
2498       irowm = bufr;
2499       icolm = bufc;
2500     } else {
2501       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2502       irowm = bufr;
2503       icolm = bufc;
2504     }
2505     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2506     else irowm = irow;
2507     if (mat->cmap->mapping) {
2508       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2509         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2510       } else icolm = irowm;
2511     } else icolm = icol;
2512     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2513     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2514   }
2515   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2516   PetscFunctionReturn(PETSC_SUCCESS);
2517 }
2518 
2519 /*@
2520   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2521 
2522   Collective
2523 
2524   Input Parameters:
2525 + mat - the matrix
2526 - x   - the vector to be multiplied
2527 
2528   Output Parameter:
2529 . y - the result
2530 
2531   Level: developer
2532 
2533   Note:
2534   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2535   call `MatMultDiagonalBlock`(A,y,y).
2536 
2537 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2538 @*/
2539 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2540 {
2541   PetscFunctionBegin;
2542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2543   PetscValidType(mat, 1);
2544   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2545   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2546 
2547   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2548   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2549   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2550   MatCheckPreallocated(mat, 1);
2551 
2552   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2553   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2554   PetscFunctionReturn(PETSC_SUCCESS);
2555 }
2556 
2557 /*@
2558   MatMult - Computes the matrix-vector product, $y = Ax$.
2559 
2560   Neighbor-wise Collective
2561 
2562   Input Parameters:
2563 + mat - the matrix
2564 - x   - the vector to be multiplied
2565 
2566   Output Parameter:
2567 . y - the result
2568 
2569   Level: beginner
2570 
2571   Note:
2572   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2573   call `MatMult`(A,y,y).
2574 
2575 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2576 @*/
2577 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2578 {
2579   PetscFunctionBegin;
2580   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2581   PetscValidType(mat, 1);
2582   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2583   VecCheckAssembled(x);
2584   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2585   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2586   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2587   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2588   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);
2589   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);
2590   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);
2591   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);
2592   PetscCall(VecSetErrorIfLocked(y, 3));
2593   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2594   MatCheckPreallocated(mat, 1);
2595 
2596   PetscCall(VecLockReadPush(x));
2597   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2598   PetscUseTypeMethod(mat, mult, x, y);
2599   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2600   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2601   PetscCall(VecLockReadPop(x));
2602   PetscFunctionReturn(PETSC_SUCCESS);
2603 }
2604 
2605 /*@
2606   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2607 
2608   Neighbor-wise Collective
2609 
2610   Input Parameters:
2611 + mat - the matrix
2612 - x   - the vector to be multiplied
2613 
2614   Output Parameter:
2615 . y - the result
2616 
2617   Level: beginner
2618 
2619   Notes:
2620   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2621   call `MatMultTranspose`(A,y,y).
2622 
2623   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2624   use `MatMultHermitianTranspose()`
2625 
2626 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2627 @*/
2628 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2629 {
2630   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2631 
2632   PetscFunctionBegin;
2633   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2634   PetscValidType(mat, 1);
2635   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2636   VecCheckAssembled(x);
2637   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2638 
2639   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2640   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2641   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2642   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);
2643   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);
2644   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);
2645   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);
2646   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2647   MatCheckPreallocated(mat, 1);
2648 
2649   if (!mat->ops->multtranspose) {
2650     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2651     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);
2652   } else op = mat->ops->multtranspose;
2653   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2654   PetscCall(VecLockReadPush(x));
2655   PetscCall((*op)(mat, x, y));
2656   PetscCall(VecLockReadPop(x));
2657   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2658   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2659   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2660   PetscFunctionReturn(PETSC_SUCCESS);
2661 }
2662 
2663 /*@
2664   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2665 
2666   Neighbor-wise Collective
2667 
2668   Input Parameters:
2669 + mat - the matrix
2670 - x   - the vector to be multiplied
2671 
2672   Output Parameter:
2673 . y - the result
2674 
2675   Level: beginner
2676 
2677   Notes:
2678   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2679   call `MatMultHermitianTranspose`(A,y,y).
2680 
2681   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2682 
2683   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2684 
2685 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2686 @*/
2687 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2688 {
2689   PetscFunctionBegin;
2690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2691   PetscValidType(mat, 1);
2692   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2693   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2694 
2695   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2696   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2697   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2698   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);
2699   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);
2700   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);
2701   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);
2702   MatCheckPreallocated(mat, 1);
2703 
2704   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2705 #if defined(PETSC_USE_COMPLEX)
2706   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2707     PetscCall(VecLockReadPush(x));
2708     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2709     else PetscUseTypeMethod(mat, mult, x, y);
2710     PetscCall(VecLockReadPop(x));
2711   } else {
2712     Vec w;
2713     PetscCall(VecDuplicate(x, &w));
2714     PetscCall(VecCopy(x, w));
2715     PetscCall(VecConjugate(w));
2716     PetscCall(MatMultTranspose(mat, w, y));
2717     PetscCall(VecDestroy(&w));
2718     PetscCall(VecConjugate(y));
2719   }
2720   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2721 #else
2722   PetscCall(MatMultTranspose(mat, x, y));
2723 #endif
2724   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2725   PetscFunctionReturn(PETSC_SUCCESS);
2726 }
2727 
2728 /*@
2729   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2730 
2731   Neighbor-wise Collective
2732 
2733   Input Parameters:
2734 + mat - the matrix
2735 . v1  - the vector to be multiplied by `mat`
2736 - v2  - the vector to be added to the result
2737 
2738   Output Parameter:
2739 . v3 - the result
2740 
2741   Level: beginner
2742 
2743   Note:
2744   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2745   call `MatMultAdd`(A,v1,v2,v1).
2746 
2747 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2748 @*/
2749 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2750 {
2751   PetscFunctionBegin;
2752   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2753   PetscValidType(mat, 1);
2754   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2755   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2756   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2757 
2758   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2759   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2760   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);
2761   /* 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);
2762      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); */
2763   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);
2764   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);
2765   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2766   MatCheckPreallocated(mat, 1);
2767 
2768   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2769   PetscCall(VecLockReadPush(v1));
2770   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2771   PetscCall(VecLockReadPop(v1));
2772   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2773   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2774   PetscFunctionReturn(PETSC_SUCCESS);
2775 }
2776 
2777 /*@
2778   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2779 
2780   Neighbor-wise Collective
2781 
2782   Input Parameters:
2783 + mat - the matrix
2784 . v1  - the vector to be multiplied by the transpose of the matrix
2785 - v2  - the vector to be added to the result
2786 
2787   Output Parameter:
2788 . v3 - the result
2789 
2790   Level: beginner
2791 
2792   Note:
2793   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2794   call `MatMultTransposeAdd`(A,v1,v2,v1).
2795 
2796 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2797 @*/
2798 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2799 {
2800   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2801 
2802   PetscFunctionBegin;
2803   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2804   PetscValidType(mat, 1);
2805   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2806   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2807   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2808 
2809   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2810   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2811   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);
2812   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);
2813   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);
2814   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2815   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2816   MatCheckPreallocated(mat, 1);
2817 
2818   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2819   PetscCall(VecLockReadPush(v1));
2820   PetscCall((*op)(mat, v1, v2, v3));
2821   PetscCall(VecLockReadPop(v1));
2822   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2823   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2824   PetscFunctionReturn(PETSC_SUCCESS);
2825 }
2826 
2827 /*@
2828   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2829 
2830   Neighbor-wise Collective
2831 
2832   Input Parameters:
2833 + mat - the matrix
2834 . v1  - the vector to be multiplied by the Hermitian transpose
2835 - v2  - the vector to be added to the result
2836 
2837   Output Parameter:
2838 . v3 - the result
2839 
2840   Level: beginner
2841 
2842   Note:
2843   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2844   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2845 
2846 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2847 @*/
2848 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2849 {
2850   PetscFunctionBegin;
2851   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2852   PetscValidType(mat, 1);
2853   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2854   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2855   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2856 
2857   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2858   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2859   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2860   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);
2861   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);
2862   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);
2863   MatCheckPreallocated(mat, 1);
2864 
2865   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2866   PetscCall(VecLockReadPush(v1));
2867   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2868   else {
2869     Vec w, z;
2870     PetscCall(VecDuplicate(v1, &w));
2871     PetscCall(VecCopy(v1, w));
2872     PetscCall(VecConjugate(w));
2873     PetscCall(VecDuplicate(v3, &z));
2874     PetscCall(MatMultTranspose(mat, w, z));
2875     PetscCall(VecDestroy(&w));
2876     PetscCall(VecConjugate(z));
2877     if (v2 != v3) {
2878       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2879     } else {
2880       PetscCall(VecAXPY(v3, 1.0, z));
2881     }
2882     PetscCall(VecDestroy(&z));
2883   }
2884   PetscCall(VecLockReadPop(v1));
2885   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2886   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2887   PetscFunctionReturn(PETSC_SUCCESS);
2888 }
2889 
2890 /*@C
2891   MatGetFactorType - gets the type of factorization a matrix is
2892 
2893   Not Collective
2894 
2895   Input Parameter:
2896 . mat - the matrix
2897 
2898   Output Parameter:
2899 . 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`
2900 
2901   Level: intermediate
2902 
2903 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2904           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2905 @*/
2906 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2907 {
2908   PetscFunctionBegin;
2909   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2910   PetscValidType(mat, 1);
2911   PetscAssertPointer(t, 2);
2912   *t = mat->factortype;
2913   PetscFunctionReturn(PETSC_SUCCESS);
2914 }
2915 
2916 /*@C
2917   MatSetFactorType - sets the type of factorization a matrix is
2918 
2919   Logically Collective
2920 
2921   Input Parameters:
2922 + mat - the matrix
2923 - 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`
2924 
2925   Level: intermediate
2926 
2927 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2928           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2929 @*/
2930 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2931 {
2932   PetscFunctionBegin;
2933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2934   PetscValidType(mat, 1);
2935   mat->factortype = t;
2936   PetscFunctionReturn(PETSC_SUCCESS);
2937 }
2938 
2939 /*@C
2940   MatGetInfo - Returns information about matrix storage (number of
2941   nonzeros, memory, etc.).
2942 
2943   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2944 
2945   Input Parameters:
2946 + mat  - the matrix
2947 - 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)
2948 
2949   Output Parameter:
2950 . info - matrix information context
2951 
2952   Options Database Key:
2953 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2954 
2955   Notes:
2956   The `MatInfo` context contains a variety of matrix data, including
2957   number of nonzeros allocated and used, number of mallocs during
2958   matrix assembly, etc.  Additional information for factored matrices
2959   is provided (such as the fill ratio, number of mallocs during
2960   factorization, etc.).
2961 
2962   Example:
2963   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2964   data within the MatInfo context.  For example,
2965 .vb
2966       MatInfo info;
2967       Mat     A;
2968       double  mal, nz_a, nz_u;
2969 
2970       MatGetInfo(A, MAT_LOCAL, &info);
2971       mal  = info.mallocs;
2972       nz_a = info.nz_allocated;
2973 .ve
2974 
2975   Fortran users should declare info as a double precision
2976   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2977   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2978   a complete list of parameter names.
2979 .vb
2980       double  precision info(MAT_INFO_SIZE)
2981       double  precision mal, nz_a
2982       Mat     A
2983       integer ierr
2984 
2985       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2986       mal = info(MAT_INFO_MALLOCS)
2987       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2988 .ve
2989 
2990   Level: intermediate
2991 
2992   Developer Note:
2993   The Fortran interface is not autogenerated as the
2994   interface definition cannot be generated correctly [due to `MatInfo` argument]
2995 
2996 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2997 @*/
2998 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2999 {
3000   PetscFunctionBegin;
3001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3002   PetscValidType(mat, 1);
3003   PetscAssertPointer(info, 3);
3004   MatCheckPreallocated(mat, 1);
3005   PetscUseTypeMethod(mat, getinfo, flag, info);
3006   PetscFunctionReturn(PETSC_SUCCESS);
3007 }
3008 
3009 /*
3010    This is used by external packages where it is not easy to get the info from the actual
3011    matrix factorization.
3012 */
3013 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3014 {
3015   PetscFunctionBegin;
3016   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3017   PetscFunctionReturn(PETSC_SUCCESS);
3018 }
3019 
3020 /*@C
3021   MatLUFactor - Performs in-place LU factorization of matrix.
3022 
3023   Collective
3024 
3025   Input Parameters:
3026 + mat  - the matrix
3027 . row  - row permutation
3028 . col  - column permutation
3029 - info - options for factorization, includes
3030 .vb
3031           fill - expected fill as ratio of original fill.
3032           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3033                    Run with the option -info to determine an optimal value to use
3034 .ve
3035 
3036   Level: developer
3037 
3038   Notes:
3039   Most users should employ the `KSP` interface for linear solvers
3040   instead of working directly with matrix algebra routines such as this.
3041   See, e.g., `KSPCreate()`.
3042 
3043   This changes the state of the matrix to a factored matrix; it cannot be used
3044   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3045 
3046   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3047   when not using `KSP`.
3048 
3049   Developer Note:
3050   The Fortran interface is not autogenerated as the
3051   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3052 
3053 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3054           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3055 @*/
3056 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3057 {
3058   MatFactorInfo tinfo;
3059 
3060   PetscFunctionBegin;
3061   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3062   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3063   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3064   if (info) PetscAssertPointer(info, 4);
3065   PetscValidType(mat, 1);
3066   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3067   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3068   MatCheckPreallocated(mat, 1);
3069   if (!info) {
3070     PetscCall(MatFactorInfoInitialize(&tinfo));
3071     info = &tinfo;
3072   }
3073 
3074   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3075   PetscUseTypeMethod(mat, lufactor, row, col, info);
3076   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3077   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3078   PetscFunctionReturn(PETSC_SUCCESS);
3079 }
3080 
3081 /*@C
3082   MatILUFactor - Performs in-place ILU factorization of matrix.
3083 
3084   Collective
3085 
3086   Input Parameters:
3087 + mat  - the matrix
3088 . row  - row permutation
3089 . col  - column permutation
3090 - info - structure containing
3091 .vb
3092       levels - number of levels of fill.
3093       expected fill - as ratio of original fill.
3094       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3095                 missing diagonal entries)
3096 .ve
3097 
3098   Level: developer
3099 
3100   Notes:
3101   Most users should employ the `KSP` interface for linear solvers
3102   instead of working directly with matrix algebra routines such as this.
3103   See, e.g., `KSPCreate()`.
3104 
3105   Probably really in-place only when level of fill is zero, otherwise allocates
3106   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3107   when not using `KSP`.
3108 
3109   Developer Note:
3110   The Fortran interface is not autogenerated as the
3111   interface definition cannot be generated correctly [due to MatFactorInfo]
3112 
3113 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3114 @*/
3115 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3116 {
3117   PetscFunctionBegin;
3118   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3119   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3120   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3121   PetscAssertPointer(info, 4);
3122   PetscValidType(mat, 1);
3123   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3124   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3125   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3126   MatCheckPreallocated(mat, 1);
3127 
3128   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3129   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3130   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3131   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3132   PetscFunctionReturn(PETSC_SUCCESS);
3133 }
3134 
3135 /*@C
3136   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3137   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3138 
3139   Collective
3140 
3141   Input Parameters:
3142 + fact - the factor matrix obtained with `MatGetFactor()`
3143 . mat  - the matrix
3144 . row  - the row permutation
3145 . col  - the column permutation
3146 - info - options for factorization, includes
3147 .vb
3148           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3149           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3150 .ve
3151 
3152   Level: developer
3153 
3154   Notes:
3155   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3156 
3157   Most users should employ the simplified `KSP` interface for linear solvers
3158   instead of working directly with matrix algebra routines such as this.
3159   See, e.g., `KSPCreate()`.
3160 
3161   Developer Note:
3162   The Fortran interface is not autogenerated as the
3163   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3164 
3165 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3166 @*/
3167 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3168 {
3169   MatFactorInfo tinfo;
3170 
3171   PetscFunctionBegin;
3172   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3173   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3174   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3175   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3176   if (info) PetscAssertPointer(info, 5);
3177   PetscValidType(fact, 1);
3178   PetscValidType(mat, 2);
3179   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3180   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3181   MatCheckPreallocated(mat, 2);
3182   if (!info) {
3183     PetscCall(MatFactorInfoInitialize(&tinfo));
3184     info = &tinfo;
3185   }
3186 
3187   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3188   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3189   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3190   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3191   PetscFunctionReturn(PETSC_SUCCESS);
3192 }
3193 
3194 /*@C
3195   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3196   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3197 
3198   Collective
3199 
3200   Input Parameters:
3201 + fact - the factor matrix obtained with `MatGetFactor()`
3202 . mat  - the matrix
3203 - info - options for factorization
3204 
3205   Level: developer
3206 
3207   Notes:
3208   See `MatLUFactor()` for in-place factorization.  See
3209   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3210 
3211   Most users should employ the `KSP` interface for linear solvers
3212   instead of working directly with matrix algebra routines such as this.
3213   See, e.g., `KSPCreate()`.
3214 
3215   Developer Note:
3216   The Fortran interface is not autogenerated as the
3217   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3218 
3219 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3220 @*/
3221 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3222 {
3223   MatFactorInfo tinfo;
3224 
3225   PetscFunctionBegin;
3226   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3227   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3228   PetscValidType(fact, 1);
3229   PetscValidType(mat, 2);
3230   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3231   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,
3232              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3233 
3234   MatCheckPreallocated(mat, 2);
3235   if (!info) {
3236     PetscCall(MatFactorInfoInitialize(&tinfo));
3237     info = &tinfo;
3238   }
3239 
3240   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3241   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3242   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3243   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3244   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3245   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3246   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3247   PetscFunctionReturn(PETSC_SUCCESS);
3248 }
3249 
3250 /*@C
3251   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3252   symmetric matrix.
3253 
3254   Collective
3255 
3256   Input Parameters:
3257 + mat  - the matrix
3258 . perm - row and column permutations
3259 - info - expected fill as ratio of original fill
3260 
3261   Level: developer
3262 
3263   Notes:
3264   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3265   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3266 
3267   Most users should employ the `KSP` interface for linear solvers
3268   instead of working directly with matrix algebra routines such as this.
3269   See, e.g., `KSPCreate()`.
3270 
3271   Developer Note:
3272   The Fortran interface is not autogenerated as the
3273   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3274 
3275 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3276           `MatGetOrdering()`
3277 @*/
3278 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3279 {
3280   MatFactorInfo tinfo;
3281 
3282   PetscFunctionBegin;
3283   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3284   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3285   if (info) PetscAssertPointer(info, 3);
3286   PetscValidType(mat, 1);
3287   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3288   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3289   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3290   MatCheckPreallocated(mat, 1);
3291   if (!info) {
3292     PetscCall(MatFactorInfoInitialize(&tinfo));
3293     info = &tinfo;
3294   }
3295 
3296   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3297   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3298   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3299   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3300   PetscFunctionReturn(PETSC_SUCCESS);
3301 }
3302 
3303 /*@C
3304   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3305   of a symmetric matrix.
3306 
3307   Collective
3308 
3309   Input Parameters:
3310 + fact - the factor matrix obtained with `MatGetFactor()`
3311 . mat  - the matrix
3312 . perm - row and column permutations
3313 - info - options for factorization, includes
3314 .vb
3315           fill - expected fill as ratio of original fill.
3316           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3317                    Run with the option -info to determine an optimal value to use
3318 .ve
3319 
3320   Level: developer
3321 
3322   Notes:
3323   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3324   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3325 
3326   Most users should employ the `KSP` interface for linear solvers
3327   instead of working directly with matrix algebra routines such as this.
3328   See, e.g., `KSPCreate()`.
3329 
3330   Developer Note:
3331   The Fortran interface is not autogenerated as the
3332   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3333 
3334 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3335           `MatGetOrdering()`
3336 @*/
3337 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3338 {
3339   MatFactorInfo tinfo;
3340 
3341   PetscFunctionBegin;
3342   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3343   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3344   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3345   if (info) PetscAssertPointer(info, 4);
3346   PetscValidType(fact, 1);
3347   PetscValidType(mat, 2);
3348   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3349   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3350   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3351   MatCheckPreallocated(mat, 2);
3352   if (!info) {
3353     PetscCall(MatFactorInfoInitialize(&tinfo));
3354     info = &tinfo;
3355   }
3356 
3357   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3358   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3359   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3360   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3361   PetscFunctionReturn(PETSC_SUCCESS);
3362 }
3363 
3364 /*@C
3365   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3366   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3367   `MatCholeskyFactorSymbolic()`.
3368 
3369   Collective
3370 
3371   Input Parameters:
3372 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3373 . mat  - the initial matrix that is to be factored
3374 - info - options for factorization
3375 
3376   Level: developer
3377 
3378   Note:
3379   Most users should employ the `KSP` interface for linear solvers
3380   instead of working directly with matrix algebra routines such as this.
3381   See, e.g., `KSPCreate()`.
3382 
3383   Developer Note:
3384   The Fortran interface is not autogenerated as the
3385   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3386 
3387 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3388 @*/
3389 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3390 {
3391   MatFactorInfo tinfo;
3392 
3393   PetscFunctionBegin;
3394   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3395   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3396   PetscValidType(fact, 1);
3397   PetscValidType(mat, 2);
3398   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3399   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,
3400              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3401   MatCheckPreallocated(mat, 2);
3402   if (!info) {
3403     PetscCall(MatFactorInfoInitialize(&tinfo));
3404     info = &tinfo;
3405   }
3406 
3407   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3408   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3409   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3410   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3411   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3412   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3413   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3414   PetscFunctionReturn(PETSC_SUCCESS);
3415 }
3416 
3417 /*@
3418   MatQRFactor - Performs in-place QR factorization of matrix.
3419 
3420   Collective
3421 
3422   Input Parameters:
3423 + mat  - the matrix
3424 . col  - column permutation
3425 - info - options for factorization, includes
3426 .vb
3427           fill - expected fill as ratio of original fill.
3428           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3429                    Run with the option -info to determine an optimal value to use
3430 .ve
3431 
3432   Level: developer
3433 
3434   Notes:
3435   Most users should employ the `KSP` interface for linear solvers
3436   instead of working directly with matrix algebra routines such as this.
3437   See, e.g., `KSPCreate()`.
3438 
3439   This changes the state of the matrix to a factored matrix; it cannot be used
3440   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3441 
3442   Developer Note:
3443   The Fortran interface is not autogenerated as the
3444   interface definition cannot be generated correctly [due to MatFactorInfo]
3445 
3446 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3447           `MatSetUnfactored()`
3448 @*/
3449 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3450 {
3451   PetscFunctionBegin;
3452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3453   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3454   if (info) PetscAssertPointer(info, 3);
3455   PetscValidType(mat, 1);
3456   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3457   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3458   MatCheckPreallocated(mat, 1);
3459   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3460   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3461   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3462   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3463   PetscFunctionReturn(PETSC_SUCCESS);
3464 }
3465 
3466 /*@
3467   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3468   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3469 
3470   Collective
3471 
3472   Input Parameters:
3473 + fact - the factor matrix obtained with `MatGetFactor()`
3474 . mat  - the matrix
3475 . col  - column permutation
3476 - info - options for factorization, includes
3477 .vb
3478           fill - expected fill as ratio of original fill.
3479           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3480                    Run with the option -info to determine an optimal value to use
3481 .ve
3482 
3483   Level: developer
3484 
3485   Note:
3486   Most users should employ the `KSP` interface for linear solvers
3487   instead of working directly with matrix algebra routines such as this.
3488   See, e.g., `KSPCreate()`.
3489 
3490   Developer Note:
3491   The Fortran interface is not autogenerated as the
3492   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3493 
3494 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3495 @*/
3496 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3497 {
3498   MatFactorInfo tinfo;
3499 
3500   PetscFunctionBegin;
3501   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3503   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3504   if (info) PetscAssertPointer(info, 4);
3505   PetscValidType(fact, 1);
3506   PetscValidType(mat, 2);
3507   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3508   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3509   MatCheckPreallocated(mat, 2);
3510   if (!info) {
3511     PetscCall(MatFactorInfoInitialize(&tinfo));
3512     info = &tinfo;
3513   }
3514 
3515   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3516   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3517   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3518   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3519   PetscFunctionReturn(PETSC_SUCCESS);
3520 }
3521 
3522 /*@
3523   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3524   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3525 
3526   Collective
3527 
3528   Input Parameters:
3529 + fact - the factor matrix obtained with `MatGetFactor()`
3530 . mat  - the matrix
3531 - info - options for factorization
3532 
3533   Level: developer
3534 
3535   Notes:
3536   See `MatQRFactor()` for in-place factorization.
3537 
3538   Most users should employ the `KSP` interface for linear solvers
3539   instead of working directly with matrix algebra routines such as this.
3540   See, e.g., `KSPCreate()`.
3541 
3542   Developer Note:
3543   The Fortran interface is not autogenerated as the
3544   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3545 
3546 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3547 @*/
3548 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3549 {
3550   MatFactorInfo tinfo;
3551 
3552   PetscFunctionBegin;
3553   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3555   PetscValidType(fact, 1);
3556   PetscValidType(mat, 2);
3557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3558   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,
3559              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3560 
3561   MatCheckPreallocated(mat, 2);
3562   if (!info) {
3563     PetscCall(MatFactorInfoInitialize(&tinfo));
3564     info = &tinfo;
3565   }
3566 
3567   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3568   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3569   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3570   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3571   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3572   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3573   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3574   PetscFunctionReturn(PETSC_SUCCESS);
3575 }
3576 
3577 /*@
3578   MatSolve - Solves $A x = b$, given a factored matrix.
3579 
3580   Neighbor-wise Collective
3581 
3582   Input Parameters:
3583 + mat - the factored matrix
3584 - b   - the right-hand-side vector
3585 
3586   Output Parameter:
3587 . x - the result vector
3588 
3589   Level: developer
3590 
3591   Notes:
3592   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3593   call `MatSolve`(A,x,x).
3594 
3595   Most users should employ the `KSP` interface for linear solvers
3596   instead of working directly with matrix algebra routines such as this.
3597   See, e.g., `KSPCreate()`.
3598 
3599 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3600 @*/
3601 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3602 {
3603   PetscFunctionBegin;
3604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3605   PetscValidType(mat, 1);
3606   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3607   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3608   PetscCheckSameComm(mat, 1, b, 2);
3609   PetscCheckSameComm(mat, 1, x, 3);
3610   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3611   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);
3612   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);
3613   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);
3614   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3615   MatCheckPreallocated(mat, 1);
3616 
3617   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3618   if (mat->factorerrortype) {
3619     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3620     PetscCall(VecSetInf(x));
3621   } else PetscUseTypeMethod(mat, solve, b, x);
3622   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3623   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3624   PetscFunctionReturn(PETSC_SUCCESS);
3625 }
3626 
3627 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3628 {
3629   Vec      b, x;
3630   PetscInt N, i;
3631   PetscErrorCode (*f)(Mat, Vec, Vec);
3632   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3633 
3634   PetscFunctionBegin;
3635   if (A->factorerrortype) {
3636     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3637     PetscCall(MatSetInf(X));
3638     PetscFunctionReturn(PETSC_SUCCESS);
3639   }
3640   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3641   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3642   PetscCall(MatBoundToCPU(A, &Abound));
3643   if (!Abound) {
3644     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3645     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3646   }
3647 #if PetscDefined(HAVE_CUDA)
3648   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3649   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3650 #elif PetscDefined(HAVE_HIP)
3651   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3652   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3653 #endif
3654   PetscCall(MatGetSize(B, NULL, &N));
3655   for (i = 0; i < N; i++) {
3656     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3657     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3658     PetscCall((*f)(A, b, x));
3659     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3660     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3661   }
3662   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3663   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3664   PetscFunctionReturn(PETSC_SUCCESS);
3665 }
3666 
3667 /*@
3668   MatMatSolve - Solves $A X = B$, given a factored matrix.
3669 
3670   Neighbor-wise Collective
3671 
3672   Input Parameters:
3673 + A - the factored matrix
3674 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3675 
3676   Output Parameter:
3677 . X - the result matrix (dense matrix)
3678 
3679   Level: developer
3680 
3681   Note:
3682   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3683   otherwise, `B` and `X` cannot be the same.
3684 
3685 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3686 @*/
3687 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3688 {
3689   PetscFunctionBegin;
3690   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3691   PetscValidType(A, 1);
3692   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3693   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3694   PetscCheckSameComm(A, 1, B, 2);
3695   PetscCheckSameComm(A, 1, X, 3);
3696   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);
3697   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);
3698   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");
3699   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3700   MatCheckPreallocated(A, 1);
3701 
3702   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3703   if (!A->ops->matsolve) {
3704     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3705     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3706   } else PetscUseTypeMethod(A, matsolve, B, X);
3707   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3708   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3709   PetscFunctionReturn(PETSC_SUCCESS);
3710 }
3711 
3712 /*@
3713   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3714 
3715   Neighbor-wise Collective
3716 
3717   Input Parameters:
3718 + A - the factored matrix
3719 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3720 
3721   Output Parameter:
3722 . X - the result matrix (dense matrix)
3723 
3724   Level: developer
3725 
3726   Note:
3727   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3728   call `MatMatSolveTranspose`(A,X,X).
3729 
3730 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3731 @*/
3732 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3733 {
3734   PetscFunctionBegin;
3735   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3736   PetscValidType(A, 1);
3737   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3738   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3739   PetscCheckSameComm(A, 1, B, 2);
3740   PetscCheckSameComm(A, 1, X, 3);
3741   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3742   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);
3743   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);
3744   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);
3745   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");
3746   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3747   MatCheckPreallocated(A, 1);
3748 
3749   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3750   if (!A->ops->matsolvetranspose) {
3751     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3752     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3753   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3754   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3755   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3756   PetscFunctionReturn(PETSC_SUCCESS);
3757 }
3758 
3759 /*@
3760   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3761 
3762   Neighbor-wise Collective
3763 
3764   Input Parameters:
3765 + A  - the factored matrix
3766 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3767 
3768   Output Parameter:
3769 . X - the result matrix (dense matrix)
3770 
3771   Level: developer
3772 
3773   Note:
3774   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
3775   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3776 
3777 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3778 @*/
3779 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3780 {
3781   PetscFunctionBegin;
3782   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3783   PetscValidType(A, 1);
3784   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3785   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3786   PetscCheckSameComm(A, 1, Bt, 2);
3787   PetscCheckSameComm(A, 1, X, 3);
3788 
3789   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3790   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);
3791   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);
3792   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");
3793   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3794   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3795   MatCheckPreallocated(A, 1);
3796 
3797   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3798   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3799   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3800   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3801   PetscFunctionReturn(PETSC_SUCCESS);
3802 }
3803 
3804 /*@
3805   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3806   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3807 
3808   Neighbor-wise Collective
3809 
3810   Input Parameters:
3811 + mat - the factored matrix
3812 - b   - the right-hand-side vector
3813 
3814   Output Parameter:
3815 . x - the result vector
3816 
3817   Level: developer
3818 
3819   Notes:
3820   `MatSolve()` should be used for most applications, as it performs
3821   a forward solve followed by a backward solve.
3822 
3823   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3824   call `MatForwardSolve`(A,x,x).
3825 
3826   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3827   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3828   `MatForwardSolve()` solves $U^T*D y = b$, and
3829   `MatBackwardSolve()` solves $U x = y$.
3830   Thus they do not provide a symmetric preconditioner.
3831 
3832 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3833 @*/
3834 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3835 {
3836   PetscFunctionBegin;
3837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3838   PetscValidType(mat, 1);
3839   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3840   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3841   PetscCheckSameComm(mat, 1, b, 2);
3842   PetscCheckSameComm(mat, 1, x, 3);
3843   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3844   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);
3845   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);
3846   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);
3847   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3848   MatCheckPreallocated(mat, 1);
3849 
3850   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3851   PetscUseTypeMethod(mat, forwardsolve, b, x);
3852   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3853   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3854   PetscFunctionReturn(PETSC_SUCCESS);
3855 }
3856 
3857 /*@
3858   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3859   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3860 
3861   Neighbor-wise Collective
3862 
3863   Input Parameters:
3864 + mat - the factored matrix
3865 - b   - the right-hand-side vector
3866 
3867   Output Parameter:
3868 . x - the result vector
3869 
3870   Level: developer
3871 
3872   Notes:
3873   `MatSolve()` should be used for most applications, as it performs
3874   a forward solve followed by a backward solve.
3875 
3876   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3877   call `MatBackwardSolve`(A,x,x).
3878 
3879   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3880   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3881   `MatForwardSolve()` solves $U^T*D y = b$, and
3882   `MatBackwardSolve()` solves $U x = y$.
3883   Thus they do not provide a symmetric preconditioner.
3884 
3885 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3886 @*/
3887 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3888 {
3889   PetscFunctionBegin;
3890   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3891   PetscValidType(mat, 1);
3892   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3893   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3894   PetscCheckSameComm(mat, 1, b, 2);
3895   PetscCheckSameComm(mat, 1, x, 3);
3896   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3897   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);
3898   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);
3899   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);
3900   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3901   MatCheckPreallocated(mat, 1);
3902 
3903   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3904   PetscUseTypeMethod(mat, backwardsolve, b, x);
3905   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3906   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3907   PetscFunctionReturn(PETSC_SUCCESS);
3908 }
3909 
3910 /*@
3911   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3912 
3913   Neighbor-wise Collective
3914 
3915   Input Parameters:
3916 + mat - the factored matrix
3917 . b   - the right-hand-side vector
3918 - y   - the vector to be added to
3919 
3920   Output Parameter:
3921 . x - the result vector
3922 
3923   Level: developer
3924 
3925   Note:
3926   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3927   call `MatSolveAdd`(A,x,y,x).
3928 
3929 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3930 @*/
3931 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3932 {
3933   PetscScalar one = 1.0;
3934   Vec         tmp;
3935 
3936   PetscFunctionBegin;
3937   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3938   PetscValidType(mat, 1);
3939   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3940   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3941   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3942   PetscCheckSameComm(mat, 1, b, 2);
3943   PetscCheckSameComm(mat, 1, y, 3);
3944   PetscCheckSameComm(mat, 1, x, 4);
3945   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3946   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);
3947   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);
3948   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);
3949   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);
3950   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);
3951   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3952   MatCheckPreallocated(mat, 1);
3953 
3954   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3955   if (mat->factorerrortype) {
3956     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3957     PetscCall(VecSetInf(x));
3958   } else if (mat->ops->solveadd) {
3959     PetscUseTypeMethod(mat, solveadd, b, y, x);
3960   } else {
3961     /* do the solve then the add manually */
3962     if (x != y) {
3963       PetscCall(MatSolve(mat, b, x));
3964       PetscCall(VecAXPY(x, one, y));
3965     } else {
3966       PetscCall(VecDuplicate(x, &tmp));
3967       PetscCall(VecCopy(x, tmp));
3968       PetscCall(MatSolve(mat, b, x));
3969       PetscCall(VecAXPY(x, one, tmp));
3970       PetscCall(VecDestroy(&tmp));
3971     }
3972   }
3973   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3974   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3975   PetscFunctionReturn(PETSC_SUCCESS);
3976 }
3977 
3978 /*@
3979   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3980 
3981   Neighbor-wise Collective
3982 
3983   Input Parameters:
3984 + mat - the factored matrix
3985 - b   - the right-hand-side vector
3986 
3987   Output Parameter:
3988 . x - the result vector
3989 
3990   Level: developer
3991 
3992   Notes:
3993   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3994   call `MatSolveTranspose`(A,x,x).
3995 
3996   Most users should employ the `KSP` interface for linear solvers
3997   instead of working directly with matrix algebra routines such as this.
3998   See, e.g., `KSPCreate()`.
3999 
4000 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4001 @*/
4002 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4003 {
4004   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4005 
4006   PetscFunctionBegin;
4007   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4008   PetscValidType(mat, 1);
4009   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4010   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4011   PetscCheckSameComm(mat, 1, b, 2);
4012   PetscCheckSameComm(mat, 1, x, 3);
4013   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4014   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);
4015   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);
4016   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4017   MatCheckPreallocated(mat, 1);
4018   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4019   if (mat->factorerrortype) {
4020     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4021     PetscCall(VecSetInf(x));
4022   } else {
4023     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4024     PetscCall((*f)(mat, b, x));
4025   }
4026   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4027   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4028   PetscFunctionReturn(PETSC_SUCCESS);
4029 }
4030 
4031 /*@
4032   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4033   factored matrix.
4034 
4035   Neighbor-wise Collective
4036 
4037   Input Parameters:
4038 + mat - the factored matrix
4039 . b   - the right-hand-side vector
4040 - y   - the vector to be added to
4041 
4042   Output Parameter:
4043 . x - the result vector
4044 
4045   Level: developer
4046 
4047   Note:
4048   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4049   call `MatSolveTransposeAdd`(A,x,y,x).
4050 
4051 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4052 @*/
4053 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4054 {
4055   PetscScalar one = 1.0;
4056   Vec         tmp;
4057   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4058 
4059   PetscFunctionBegin;
4060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4061   PetscValidType(mat, 1);
4062   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4063   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4064   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4065   PetscCheckSameComm(mat, 1, b, 2);
4066   PetscCheckSameComm(mat, 1, y, 3);
4067   PetscCheckSameComm(mat, 1, x, 4);
4068   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4069   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);
4070   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);
4071   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);
4072   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);
4073   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4074   MatCheckPreallocated(mat, 1);
4075 
4076   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4077   if (mat->factorerrortype) {
4078     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4079     PetscCall(VecSetInf(x));
4080   } else if (f) {
4081     PetscCall((*f)(mat, b, y, x));
4082   } else {
4083     /* do the solve then the add manually */
4084     if (x != y) {
4085       PetscCall(MatSolveTranspose(mat, b, x));
4086       PetscCall(VecAXPY(x, one, y));
4087     } else {
4088       PetscCall(VecDuplicate(x, &tmp));
4089       PetscCall(VecCopy(x, tmp));
4090       PetscCall(MatSolveTranspose(mat, b, x));
4091       PetscCall(VecAXPY(x, one, tmp));
4092       PetscCall(VecDestroy(&tmp));
4093     }
4094   }
4095   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4096   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4097   PetscFunctionReturn(PETSC_SUCCESS);
4098 }
4099 
4100 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4101 /*@
4102   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4103 
4104   Neighbor-wise Collective
4105 
4106   Input Parameters:
4107 + mat   - the matrix
4108 . b     - the right hand side
4109 . omega - the relaxation factor
4110 . flag  - flag indicating the type of SOR (see below)
4111 . shift - diagonal shift
4112 . its   - the number of iterations
4113 - lits  - the number of local iterations
4114 
4115   Output Parameter:
4116 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4117 
4118   SOR Flags:
4119 +     `SOR_FORWARD_SWEEP` - forward SOR
4120 .     `SOR_BACKWARD_SWEEP` - backward SOR
4121 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4122 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4123 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4124 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4125 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4126 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4127   upper/lower triangular part of matrix to
4128   vector (with omega)
4129 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4130 
4131   Level: developer
4132 
4133   Notes:
4134   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4135   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4136   on each processor.
4137 
4138   Application programmers will not generally use `MatSOR()` directly,
4139   but instead will employ the `KSP`/`PC` interface.
4140 
4141   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4142 
4143   Most users should employ the `KSP` interface for linear solvers
4144   instead of working directly with matrix algebra routines such as this.
4145   See, e.g., `KSPCreate()`.
4146 
4147   Vectors `x` and `b` CANNOT be the same
4148 
4149   The flags are implemented as bitwise inclusive or operations.
4150   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4151   to specify a zero initial guess for SSOR.
4152 
4153   Developer Note:
4154   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4155 
4156 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4157 @*/
4158 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4159 {
4160   PetscFunctionBegin;
4161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4162   PetscValidType(mat, 1);
4163   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4164   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4165   PetscCheckSameComm(mat, 1, b, 2);
4166   PetscCheckSameComm(mat, 1, x, 8);
4167   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4168   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4169   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);
4170   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);
4171   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);
4172   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4173   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4174   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4175 
4176   MatCheckPreallocated(mat, 1);
4177   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4178   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4179   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4180   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4181   PetscFunctionReturn(PETSC_SUCCESS);
4182 }
4183 
4184 /*
4185       Default matrix copy routine.
4186 */
4187 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4188 {
4189   PetscInt           i, rstart = 0, rend = 0, nz;
4190   const PetscInt    *cwork;
4191   const PetscScalar *vwork;
4192 
4193   PetscFunctionBegin;
4194   if (B->assembled) PetscCall(MatZeroEntries(B));
4195   if (str == SAME_NONZERO_PATTERN) {
4196     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4197     for (i = rstart; i < rend; i++) {
4198       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4199       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4200       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4201     }
4202   } else {
4203     PetscCall(MatAYPX(B, 0.0, A, str));
4204   }
4205   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4206   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4207   PetscFunctionReturn(PETSC_SUCCESS);
4208 }
4209 
4210 /*@
4211   MatCopy - Copies a matrix to another matrix.
4212 
4213   Collective
4214 
4215   Input Parameters:
4216 + A   - the matrix
4217 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4218 
4219   Output Parameter:
4220 . B - where the copy is put
4221 
4222   Level: intermediate
4223 
4224   Notes:
4225   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4226 
4227   `MatCopy()` copies the matrix entries of a matrix to another existing
4228   matrix (after first zeroing the second matrix).  A related routine is
4229   `MatConvert()`, which first creates a new matrix and then copies the data.
4230 
4231 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4232 @*/
4233 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4234 {
4235   PetscInt i;
4236 
4237   PetscFunctionBegin;
4238   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4239   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4240   PetscValidType(A, 1);
4241   PetscValidType(B, 2);
4242   PetscCheckSameComm(A, 1, B, 2);
4243   MatCheckPreallocated(B, 2);
4244   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4245   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4246   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,
4247              A->cmap->N, B->cmap->N);
4248   MatCheckPreallocated(A, 1);
4249   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4250 
4251   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4252   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4253   else PetscCall(MatCopy_Basic(A, B, str));
4254 
4255   B->stencil.dim = A->stencil.dim;
4256   B->stencil.noc = A->stencil.noc;
4257   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4258     B->stencil.dims[i]   = A->stencil.dims[i];
4259     B->stencil.starts[i] = A->stencil.starts[i];
4260   }
4261 
4262   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4263   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4264   PetscFunctionReturn(PETSC_SUCCESS);
4265 }
4266 
4267 /*@C
4268   MatConvert - Converts a matrix to another matrix, either of the same
4269   or different type.
4270 
4271   Collective
4272 
4273   Input Parameters:
4274 + mat     - the matrix
4275 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4276    same type as the original matrix.
4277 - reuse   - denotes if the destination matrix is to be created or reused.
4278    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
4279    `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).
4280 
4281   Output Parameter:
4282 . M - pointer to place new matrix
4283 
4284   Level: intermediate
4285 
4286   Notes:
4287   `MatConvert()` first creates a new matrix and then copies the data from
4288   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4289   entries of one matrix to another already existing matrix context.
4290 
4291   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4292   the MPI communicator of the generated matrix is always the same as the communicator
4293   of the input matrix.
4294 
4295 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4296 @*/
4297 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4298 {
4299   PetscBool  sametype, issame, flg;
4300   PetscBool3 issymmetric, ishermitian;
4301   char       convname[256], mtype[256];
4302   Mat        B;
4303 
4304   PetscFunctionBegin;
4305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4306   PetscValidType(mat, 1);
4307   PetscAssertPointer(M, 4);
4308   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4309   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4310   MatCheckPreallocated(mat, 1);
4311 
4312   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4313   if (flg) newtype = mtype;
4314 
4315   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4316   PetscCall(PetscStrcmp(newtype, "same", &issame));
4317   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4318   if (reuse == MAT_REUSE_MATRIX) {
4319     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4320     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4321   }
4322 
4323   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4324     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4325     PetscFunctionReturn(PETSC_SUCCESS);
4326   }
4327 
4328   /* Cache Mat options because some converters use MatHeaderReplace  */
4329   issymmetric = mat->symmetric;
4330   ishermitian = mat->hermitian;
4331 
4332   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4333     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4334     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4335   } else {
4336     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4337     const char *prefix[3]                                 = {"seq", "mpi", ""};
4338     PetscInt    i;
4339     /*
4340        Order of precedence:
4341        0) See if newtype is a superclass of the current matrix.
4342        1) See if a specialized converter is known to the current matrix.
4343        2) See if a specialized converter is known to the desired matrix class.
4344        3) See if a good general converter is registered for the desired class
4345           (as of 6/27/03 only MATMPIADJ falls into this category).
4346        4) See if a good general converter is known for the current matrix.
4347        5) Use a really basic converter.
4348     */
4349 
4350     /* 0) See if newtype is a superclass of the current matrix.
4351           i.e mat is mpiaij and newtype is aij */
4352     for (i = 0; i < 2; i++) {
4353       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4354       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4355       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4356       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4357       if (flg) {
4358         if (reuse == MAT_INPLACE_MATRIX) {
4359           PetscCall(PetscInfo(mat, "Early return\n"));
4360           PetscFunctionReturn(PETSC_SUCCESS);
4361         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4362           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4363           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4364           PetscFunctionReturn(PETSC_SUCCESS);
4365         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4366           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4367           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4368           PetscFunctionReturn(PETSC_SUCCESS);
4369         }
4370       }
4371     }
4372     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4373     for (i = 0; i < 3; i++) {
4374       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4375       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4380       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4381       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4382       if (conv) goto foundconv;
4383     }
4384 
4385     /* 2)  See if a specialized converter is known to the desired matrix class. */
4386     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4387     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4388     PetscCall(MatSetType(B, newtype));
4389     for (i = 0; i < 3; i++) {
4390       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4391       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4396       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4397       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4398       if (conv) {
4399         PetscCall(MatDestroy(&B));
4400         goto foundconv;
4401       }
4402     }
4403 
4404     /* 3) See if a good general converter is registered for the desired class */
4405     conv = B->ops->convertfrom;
4406     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4407     PetscCall(MatDestroy(&B));
4408     if (conv) goto foundconv;
4409 
4410     /* 4) See if a good general converter is known for the current matrix */
4411     if (mat->ops->convert) conv = mat->ops->convert;
4412     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4413     if (conv) goto foundconv;
4414 
4415     /* 5) Use a really basic converter. */
4416     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4417     conv = MatConvert_Basic;
4418 
4419   foundconv:
4420     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4421     PetscCall((*conv)(mat, newtype, reuse, M));
4422     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4423       /* the block sizes must be same if the mappings are copied over */
4424       (*M)->rmap->bs = mat->rmap->bs;
4425       (*M)->cmap->bs = mat->cmap->bs;
4426       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4427       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4428       (*M)->rmap->mapping = mat->rmap->mapping;
4429       (*M)->cmap->mapping = mat->cmap->mapping;
4430     }
4431     (*M)->stencil.dim = mat->stencil.dim;
4432     (*M)->stencil.noc = mat->stencil.noc;
4433     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4434       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4435       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4436     }
4437     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4438   }
4439   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4440 
4441   /* Copy Mat options */
4442   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4443   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4444   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4445   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4446   PetscFunctionReturn(PETSC_SUCCESS);
4447 }
4448 
4449 /*@C
4450   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4451 
4452   Not Collective
4453 
4454   Input Parameter:
4455 . mat - the matrix, must be a factored matrix
4456 
4457   Output Parameter:
4458 . type - the string name of the package (do not free this string)
4459 
4460   Level: intermediate
4461 
4462   Fortran Note:
4463   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4464 
4465 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4466 @*/
4467 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4468 {
4469   PetscErrorCode (*conv)(Mat, MatSolverType *);
4470 
4471   PetscFunctionBegin;
4472   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4473   PetscValidType(mat, 1);
4474   PetscAssertPointer(type, 2);
4475   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4476   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4477   if (conv) PetscCall((*conv)(mat, type));
4478   else *type = MATSOLVERPETSC;
4479   PetscFunctionReturn(PETSC_SUCCESS);
4480 }
4481 
4482 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4483 struct _MatSolverTypeForSpecifcType {
4484   MatType mtype;
4485   /* no entry for MAT_FACTOR_NONE */
4486   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4487   MatSolverTypeForSpecifcType next;
4488 };
4489 
4490 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4491 struct _MatSolverTypeHolder {
4492   char                       *name;
4493   MatSolverTypeForSpecifcType handlers;
4494   MatSolverTypeHolder         next;
4495 };
4496 
4497 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4498 
4499 /*@C
4500   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4501 
4502   Input Parameters:
4503 + package      - name of the package, for example petsc or superlu
4504 . mtype        - the matrix type that works with this package
4505 . ftype        - the type of factorization supported by the package
4506 - createfactor - routine that will create the factored matrix ready to be used
4507 
4508   Level: developer
4509 
4510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4511   `MatGetFactor()`
4512 @*/
4513 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4514 {
4515   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4516   PetscBool                   flg;
4517   MatSolverTypeForSpecifcType inext, iprev = NULL;
4518 
4519   PetscFunctionBegin;
4520   PetscCall(MatInitializePackage());
4521   if (!next) {
4522     PetscCall(PetscNew(&MatSolverTypeHolders));
4523     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4524     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4525     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4526     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4527     PetscFunctionReturn(PETSC_SUCCESS);
4528   }
4529   while (next) {
4530     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4531     if (flg) {
4532       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4533       inext = next->handlers;
4534       while (inext) {
4535         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4536         if (flg) {
4537           inext->createfactor[(int)ftype - 1] = createfactor;
4538           PetscFunctionReturn(PETSC_SUCCESS);
4539         }
4540         iprev = inext;
4541         inext = inext->next;
4542       }
4543       PetscCall(PetscNew(&iprev->next));
4544       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4545       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4546       PetscFunctionReturn(PETSC_SUCCESS);
4547     }
4548     prev = next;
4549     next = next->next;
4550   }
4551   PetscCall(PetscNew(&prev->next));
4552   PetscCall(PetscStrallocpy(package, &prev->next->name));
4553   PetscCall(PetscNew(&prev->next->handlers));
4554   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4555   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4556   PetscFunctionReturn(PETSC_SUCCESS);
4557 }
4558 
4559 /*@C
4560   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4561 
4562   Input Parameters:
4563 + 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
4564 . ftype - the type of factorization supported by the type
4565 - mtype - the matrix type that works with this type
4566 
4567   Output Parameters:
4568 + foundtype    - `PETSC_TRUE` if the type was registered
4569 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4570 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4571 
4572   Calling sequence of `createfactor`:
4573 + A     - the matrix providing the factor matrix
4574 . mtype - the `MatType` of the factor requested
4575 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4576 
4577   Level: developer
4578 
4579   Note:
4580   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4581   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4582   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4583 
4584 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4585           `MatInitializePackage()`
4586 @*/
4587 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4588 {
4589   MatSolverTypeHolder         next = MatSolverTypeHolders;
4590   PetscBool                   flg;
4591   MatSolverTypeForSpecifcType inext;
4592 
4593   PetscFunctionBegin;
4594   if (foundtype) *foundtype = PETSC_FALSE;
4595   if (foundmtype) *foundmtype = PETSC_FALSE;
4596   if (createfactor) *createfactor = NULL;
4597 
4598   if (type) {
4599     while (next) {
4600       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4601       if (flg) {
4602         if (foundtype) *foundtype = PETSC_TRUE;
4603         inext = next->handlers;
4604         while (inext) {
4605           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4606           if (flg) {
4607             if (foundmtype) *foundmtype = PETSC_TRUE;
4608             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4609             PetscFunctionReturn(PETSC_SUCCESS);
4610           }
4611           inext = inext->next;
4612         }
4613       }
4614       next = next->next;
4615     }
4616   } else {
4617     while (next) {
4618       inext = next->handlers;
4619       while (inext) {
4620         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4621         if (flg && inext->createfactor[(int)ftype - 1]) {
4622           if (foundtype) *foundtype = PETSC_TRUE;
4623           if (foundmtype) *foundmtype = PETSC_TRUE;
4624           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4625           PetscFunctionReturn(PETSC_SUCCESS);
4626         }
4627         inext = inext->next;
4628       }
4629       next = next->next;
4630     }
4631     /* try with base classes inext->mtype */
4632     next = MatSolverTypeHolders;
4633     while (next) {
4634       inext = next->handlers;
4635       while (inext) {
4636         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4637         if (flg && inext->createfactor[(int)ftype - 1]) {
4638           if (foundtype) *foundtype = PETSC_TRUE;
4639           if (foundmtype) *foundmtype = PETSC_TRUE;
4640           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4641           PetscFunctionReturn(PETSC_SUCCESS);
4642         }
4643         inext = inext->next;
4644       }
4645       next = next->next;
4646     }
4647   }
4648   PetscFunctionReturn(PETSC_SUCCESS);
4649 }
4650 
4651 PetscErrorCode MatSolverTypeDestroy(void)
4652 {
4653   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4654   MatSolverTypeForSpecifcType inext, iprev;
4655 
4656   PetscFunctionBegin;
4657   while (next) {
4658     PetscCall(PetscFree(next->name));
4659     inext = next->handlers;
4660     while (inext) {
4661       PetscCall(PetscFree(inext->mtype));
4662       iprev = inext;
4663       inext = inext->next;
4664       PetscCall(PetscFree(iprev));
4665     }
4666     prev = next;
4667     next = next->next;
4668     PetscCall(PetscFree(prev));
4669   }
4670   MatSolverTypeHolders = NULL;
4671   PetscFunctionReturn(PETSC_SUCCESS);
4672 }
4673 
4674 /*@C
4675   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4676 
4677   Logically Collective
4678 
4679   Input Parameter:
4680 . mat - the matrix
4681 
4682   Output Parameter:
4683 . flg - `PETSC_TRUE` if uses the ordering
4684 
4685   Level: developer
4686 
4687   Note:
4688   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4689   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4690 
4691 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4692 @*/
4693 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4694 {
4695   PetscFunctionBegin;
4696   *flg = mat->canuseordering;
4697   PetscFunctionReturn(PETSC_SUCCESS);
4698 }
4699 
4700 /*@C
4701   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4702 
4703   Logically Collective
4704 
4705   Input Parameters:
4706 + mat   - the matrix obtained with `MatGetFactor()`
4707 - ftype - the factorization type to be used
4708 
4709   Output Parameter:
4710 . otype - the preferred ordering type
4711 
4712   Level: developer
4713 
4714 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4715 @*/
4716 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4717 {
4718   PetscFunctionBegin;
4719   *otype = mat->preferredordering[ftype];
4720   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4721   PetscFunctionReturn(PETSC_SUCCESS);
4722 }
4723 
4724 /*@C
4725   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4726 
4727   Collective
4728 
4729   Input Parameters:
4730 + mat   - the matrix
4731 . 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
4732           the other criteria is returned
4733 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4734 
4735   Output Parameter:
4736 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4737 
4738   Options Database Keys:
4739 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4740 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4741                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4742 
4743   Level: intermediate
4744 
4745   Notes:
4746   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4747   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4748 
4749   Users usually access the factorization solvers via `KSP`
4750 
4751   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4752   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
4753 
4754   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4755   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4756   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4757 
4758   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4759   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4760   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4761 
4762   Developer Note:
4763   This should actually be called `MatCreateFactor()` since it creates a new factor object
4764 
4765 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4766           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4767           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4768 @*/
4769 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4770 {
4771   PetscBool foundtype, foundmtype;
4772   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4773 
4774   PetscFunctionBegin;
4775   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4776   PetscValidType(mat, 1);
4777 
4778   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4779   MatCheckPreallocated(mat, 1);
4780 
4781   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4782   if (!foundtype) {
4783     if (type) {
4784       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],
4785               ((PetscObject)mat)->type_name, type);
4786     } else {
4787       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);
4788     }
4789   }
4790   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4791   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);
4792 
4793   PetscCall((*conv)(mat, ftype, f));
4794   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4795   PetscFunctionReturn(PETSC_SUCCESS);
4796 }
4797 
4798 /*@C
4799   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4800 
4801   Not Collective
4802 
4803   Input Parameters:
4804 + mat   - the matrix
4805 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4806 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4807 
4808   Output Parameter:
4809 . flg - PETSC_TRUE if the factorization is available
4810 
4811   Level: intermediate
4812 
4813   Notes:
4814   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4815   such as pastix, superlu, mumps etc.
4816 
4817   PETSc must have been ./configure to use the external solver, using the option --download-package
4818 
4819   Developer Note:
4820   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4821 
4822 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4823           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4824 @*/
4825 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4826 {
4827   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4828 
4829   PetscFunctionBegin;
4830   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4831   PetscValidType(mat, 1);
4832   PetscAssertPointer(flg, 4);
4833 
4834   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4835   MatCheckPreallocated(mat, 1);
4836 
4837   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4838   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4839   PetscFunctionReturn(PETSC_SUCCESS);
4840 }
4841 
4842 /*@
4843   MatDuplicate - Duplicates a matrix including the non-zero structure.
4844 
4845   Collective
4846 
4847   Input Parameters:
4848 + mat - the matrix
4849 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4850         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4851 
4852   Output Parameter:
4853 . M - pointer to place new matrix
4854 
4855   Level: intermediate
4856 
4857   Notes:
4858   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4859 
4860   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4861 
4862   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.
4863 
4864   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4865   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4866   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4867 
4868 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4869 @*/
4870 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4871 {
4872   Mat         B;
4873   VecType     vtype;
4874   PetscInt    i;
4875   PetscObject dm, container_h, container_d;
4876   void (*viewf)(void);
4877 
4878   PetscFunctionBegin;
4879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4880   PetscValidType(mat, 1);
4881   PetscAssertPointer(M, 3);
4882   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4883   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4884   MatCheckPreallocated(mat, 1);
4885 
4886   *M = NULL;
4887   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4888   PetscUseTypeMethod(mat, duplicate, op, M);
4889   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4890   B = *M;
4891 
4892   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4893   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4894   PetscCall(MatGetVecType(mat, &vtype));
4895   PetscCall(MatSetVecType(B, vtype));
4896 
4897   B->stencil.dim = mat->stencil.dim;
4898   B->stencil.noc = mat->stencil.noc;
4899   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4900     B->stencil.dims[i]   = mat->stencil.dims[i];
4901     B->stencil.starts[i] = mat->stencil.starts[i];
4902   }
4903 
4904   B->nooffproczerorows = mat->nooffproczerorows;
4905   B->nooffprocentries  = mat->nooffprocentries;
4906 
4907   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4908   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4909   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4910   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4911   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4912   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4913   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4914   PetscFunctionReturn(PETSC_SUCCESS);
4915 }
4916 
4917 /*@
4918   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4919 
4920   Logically Collective
4921 
4922   Input Parameter:
4923 . mat - the matrix
4924 
4925   Output Parameter:
4926 . v - the diagonal of the matrix
4927 
4928   Level: intermediate
4929 
4930   Note:
4931   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4932   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4933   is larger than `ndiag`, the values of the remaining entries are unspecified.
4934 
4935   Currently only correct in parallel for square matrices.
4936 
4937 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4938 @*/
4939 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4940 {
4941   PetscFunctionBegin;
4942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4943   PetscValidType(mat, 1);
4944   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4945   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4946   MatCheckPreallocated(mat, 1);
4947   if (PetscDefined(USE_DEBUG)) {
4948     PetscInt nv, row, col, ndiag;
4949 
4950     PetscCall(VecGetLocalSize(v, &nv));
4951     PetscCall(MatGetLocalSize(mat, &row, &col));
4952     ndiag = PetscMin(row, col);
4953     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);
4954   }
4955 
4956   PetscUseTypeMethod(mat, getdiagonal, v);
4957   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4958   PetscFunctionReturn(PETSC_SUCCESS);
4959 }
4960 
4961 /*@C
4962   MatGetRowMin - Gets the minimum value (of the real part) of each
4963   row of the matrix
4964 
4965   Logically Collective
4966 
4967   Input Parameter:
4968 . mat - the matrix
4969 
4970   Output Parameters:
4971 + v   - the vector for storing the maximums
4972 - idx - the indices of the column found for each row (optional)
4973 
4974   Level: intermediate
4975 
4976   Note:
4977   The result of this call are the same as if one converted the matrix to dense format
4978   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4979 
4980   This code is only implemented for a couple of matrix formats.
4981 
4982 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4983           `MatGetRowMax()`
4984 @*/
4985 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4986 {
4987   PetscFunctionBegin;
4988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4989   PetscValidType(mat, 1);
4990   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4991   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4992 
4993   if (!mat->cmap->N) {
4994     PetscCall(VecSet(v, PETSC_MAX_REAL));
4995     if (idx) {
4996       PetscInt i, m = mat->rmap->n;
4997       for (i = 0; i < m; i++) idx[i] = -1;
4998     }
4999   } else {
5000     MatCheckPreallocated(mat, 1);
5001   }
5002   PetscUseTypeMethod(mat, getrowmin, v, idx);
5003   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5004   PetscFunctionReturn(PETSC_SUCCESS);
5005 }
5006 
5007 /*@C
5008   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5009   row of the matrix
5010 
5011   Logically Collective
5012 
5013   Input Parameter:
5014 . mat - the matrix
5015 
5016   Output Parameters:
5017 + v   - the vector for storing the minimums
5018 - idx - the indices of the column found for each row (or `NULL` if not needed)
5019 
5020   Level: intermediate
5021 
5022   Notes:
5023   if a row is completely empty or has only 0.0 values then the `idx` value for that
5024   row is 0 (the first column).
5025 
5026   This code is only implemented for a couple of matrix formats.
5027 
5028 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5029 @*/
5030 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5031 {
5032   PetscFunctionBegin;
5033   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5034   PetscValidType(mat, 1);
5035   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5036   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5037   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5038 
5039   if (!mat->cmap->N) {
5040     PetscCall(VecSet(v, 0.0));
5041     if (idx) {
5042       PetscInt i, m = mat->rmap->n;
5043       for (i = 0; i < m; i++) idx[i] = -1;
5044     }
5045   } else {
5046     MatCheckPreallocated(mat, 1);
5047     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5048     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5049   }
5050   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5051   PetscFunctionReturn(PETSC_SUCCESS);
5052 }
5053 
5054 /*@C
5055   MatGetRowMax - Gets the maximum value (of the real part) of each
5056   row of the matrix
5057 
5058   Logically Collective
5059 
5060   Input Parameter:
5061 . mat - the matrix
5062 
5063   Output Parameters:
5064 + v   - the vector for storing the maximums
5065 - idx - the indices of the column found for each row (optional)
5066 
5067   Level: intermediate
5068 
5069   Notes:
5070   The result of this call are the same as if one converted the matrix to dense format
5071   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5072 
5073   This code is only implemented for a couple of matrix formats.
5074 
5075 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5076 @*/
5077 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5078 {
5079   PetscFunctionBegin;
5080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5081   PetscValidType(mat, 1);
5082   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5083   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5084 
5085   if (!mat->cmap->N) {
5086     PetscCall(VecSet(v, PETSC_MIN_REAL));
5087     if (idx) {
5088       PetscInt i, m = mat->rmap->n;
5089       for (i = 0; i < m; i++) idx[i] = -1;
5090     }
5091   } else {
5092     MatCheckPreallocated(mat, 1);
5093     PetscUseTypeMethod(mat, getrowmax, v, idx);
5094   }
5095   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5096   PetscFunctionReturn(PETSC_SUCCESS);
5097 }
5098 
5099 /*@C
5100   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5101   row of the matrix
5102 
5103   Logically Collective
5104 
5105   Input Parameter:
5106 . mat - the matrix
5107 
5108   Output Parameters:
5109 + v   - the vector for storing the maximums
5110 - idx - the indices of the column found for each row (or `NULL` if not needed)
5111 
5112   Level: intermediate
5113 
5114   Notes:
5115   if a row is completely empty or has only 0.0 values then the `idx` value for that
5116   row is 0 (the first column).
5117 
5118   This code is only implemented for a couple of matrix formats.
5119 
5120 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5121 @*/
5122 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5123 {
5124   PetscFunctionBegin;
5125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5126   PetscValidType(mat, 1);
5127   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5128   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5129 
5130   if (!mat->cmap->N) {
5131     PetscCall(VecSet(v, 0.0));
5132     if (idx) {
5133       PetscInt i, m = mat->rmap->n;
5134       for (i = 0; i < m; i++) idx[i] = -1;
5135     }
5136   } else {
5137     MatCheckPreallocated(mat, 1);
5138     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5139     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5140   }
5141   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5142   PetscFunctionReturn(PETSC_SUCCESS);
5143 }
5144 
5145 /*@
5146   MatGetRowSum - Gets the sum of each row of the matrix
5147 
5148   Logically or Neighborhood Collective
5149 
5150   Input Parameter:
5151 . mat - the matrix
5152 
5153   Output Parameter:
5154 . v - the vector for storing the sum of rows
5155 
5156   Level: intermediate
5157 
5158   Note:
5159   This code is slow since it is not currently specialized for different formats
5160 
5161 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5162 @*/
5163 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5164 {
5165   Vec ones;
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   MatCheckPreallocated(mat, 1);
5173   PetscCall(MatCreateVecs(mat, &ones, NULL));
5174   PetscCall(VecSet(ones, 1.));
5175   PetscCall(MatMult(mat, ones, v));
5176   PetscCall(VecDestroy(&ones));
5177   PetscFunctionReturn(PETSC_SUCCESS);
5178 }
5179 
5180 /*@
5181   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5182   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5183 
5184   Collective
5185 
5186   Input Parameter:
5187 . mat - the matrix to provide the transpose
5188 
5189   Output Parameter:
5190 . 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
5191 
5192   Level: advanced
5193 
5194   Note:
5195   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
5196   routine allows bypassing that call.
5197 
5198 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5199 @*/
5200 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5201 {
5202   PetscContainer  rB = NULL;
5203   MatParentState *rb = NULL;
5204 
5205   PetscFunctionBegin;
5206   PetscCall(PetscNew(&rb));
5207   rb->id    = ((PetscObject)mat)->id;
5208   rb->state = 0;
5209   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5210   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5211   PetscCall(PetscContainerSetPointer(rB, rb));
5212   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5213   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5214   PetscCall(PetscObjectDereference((PetscObject)rB));
5215   PetscFunctionReturn(PETSC_SUCCESS);
5216 }
5217 
5218 /*@
5219   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5220 
5221   Collective
5222 
5223   Input Parameters:
5224 + mat   - the matrix to transpose
5225 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5226 
5227   Output Parameter:
5228 . B - the transpose
5229 
5230   Level: intermediate
5231 
5232   Notes:
5233   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5234 
5235   `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
5236   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5237 
5238   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.
5239 
5240   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5241 
5242   If mat is unchanged from the last call this function returns immediately without recomputing the result
5243 
5244   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5245 
5246 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5247           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5248 @*/
5249 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5250 {
5251   PetscContainer  rB = NULL;
5252   MatParentState *rb = NULL;
5253 
5254   PetscFunctionBegin;
5255   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5256   PetscValidType(mat, 1);
5257   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5258   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5259   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5260   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5261   MatCheckPreallocated(mat, 1);
5262   if (reuse == MAT_REUSE_MATRIX) {
5263     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5264     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5265     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5266     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5267     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5268   }
5269 
5270   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5271   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5272     PetscUseTypeMethod(mat, transpose, reuse, B);
5273     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5274   }
5275   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5276 
5277   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5278   if (reuse != MAT_INPLACE_MATRIX) {
5279     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5280     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5281     rb->state        = ((PetscObject)mat)->state;
5282     rb->nonzerostate = mat->nonzerostate;
5283   }
5284   PetscFunctionReturn(PETSC_SUCCESS);
5285 }
5286 
5287 /*@
5288   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5289 
5290   Collective
5291 
5292   Input Parameter:
5293 . A - the matrix to transpose
5294 
5295   Output Parameter:
5296 . 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
5297       numerical portion.
5298 
5299   Level: intermediate
5300 
5301   Note:
5302   This is not supported for many matrix types, use `MatTranspose()` in those cases
5303 
5304 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5305 @*/
5306 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5307 {
5308   PetscFunctionBegin;
5309   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5310   PetscValidType(A, 1);
5311   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5312   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5313   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5314   PetscUseTypeMethod(A, transposesymbolic, B);
5315   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5316 
5317   PetscCall(MatTransposeSetPrecursor(A, *B));
5318   PetscFunctionReturn(PETSC_SUCCESS);
5319 }
5320 
5321 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5322 {
5323   PetscContainer  rB;
5324   MatParentState *rb;
5325 
5326   PetscFunctionBegin;
5327   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5328   PetscValidType(A, 1);
5329   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5330   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5331   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5332   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5333   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5334   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5335   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5336   PetscFunctionReturn(PETSC_SUCCESS);
5337 }
5338 
5339 /*@
5340   MatIsTranspose - Test whether a matrix is another one's transpose,
5341   or its own, in which case it tests symmetry.
5342 
5343   Collective
5344 
5345   Input Parameters:
5346 + A   - the matrix to test
5347 . B   - the matrix to test against, this can equal the first parameter
5348 - tol - tolerance, differences between entries smaller than this are counted as zero
5349 
5350   Output Parameter:
5351 . flg - the result
5352 
5353   Level: intermediate
5354 
5355   Notes:
5356   Only available for `MATAIJ` matrices.
5357 
5358   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5359   test involves parallel copies of the block off-diagonal parts of the matrix.
5360 
5361 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5362 @*/
5363 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5364 {
5365   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5366 
5367   PetscFunctionBegin;
5368   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5369   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5370   PetscAssertPointer(flg, 4);
5371   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5372   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5373   *flg = PETSC_FALSE;
5374   if (f && g) {
5375     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5376     PetscCall((*f)(A, B, tol, flg));
5377   } else {
5378     MatType mattype;
5379 
5380     PetscCall(MatGetType(f ? B : A, &mattype));
5381     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5382   }
5383   PetscFunctionReturn(PETSC_SUCCESS);
5384 }
5385 
5386 /*@
5387   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5388 
5389   Collective
5390 
5391   Input Parameters:
5392 + mat   - the matrix to transpose and complex conjugate
5393 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5394 
5395   Output Parameter:
5396 . B - the Hermitian transpose
5397 
5398   Level: intermediate
5399 
5400 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5401 @*/
5402 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5403 {
5404   PetscFunctionBegin;
5405   PetscCall(MatTranspose(mat, reuse, B));
5406 #if defined(PETSC_USE_COMPLEX)
5407   PetscCall(MatConjugate(*B));
5408 #endif
5409   PetscFunctionReturn(PETSC_SUCCESS);
5410 }
5411 
5412 /*@
5413   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5414 
5415   Collective
5416 
5417   Input Parameters:
5418 + A   - the matrix to test
5419 . B   - the matrix to test against, this can equal the first parameter
5420 - tol - tolerance, differences between entries smaller than this are counted as zero
5421 
5422   Output Parameter:
5423 . flg - the result
5424 
5425   Level: intermediate
5426 
5427   Notes:
5428   Only available for `MATAIJ` matrices.
5429 
5430   The sequential algorithm
5431   has a running time of the order of the number of nonzeros; the parallel
5432   test involves parallel copies of the block off-diagonal parts of the matrix.
5433 
5434 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5435 @*/
5436 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5437 {
5438   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5439 
5440   PetscFunctionBegin;
5441   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5442   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5443   PetscAssertPointer(flg, 4);
5444   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5445   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5446   if (f && g) {
5447     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5448     PetscCall((*f)(A, B, tol, flg));
5449   }
5450   PetscFunctionReturn(PETSC_SUCCESS);
5451 }
5452 
5453 /*@
5454   MatPermute - Creates a new matrix with rows and columns permuted from the
5455   original.
5456 
5457   Collective
5458 
5459   Input Parameters:
5460 + mat - the matrix to permute
5461 . row - row permutation, each processor supplies only the permutation for its rows
5462 - col - column permutation, each processor supplies only the permutation for its columns
5463 
5464   Output Parameter:
5465 . B - the permuted matrix
5466 
5467   Level: advanced
5468 
5469   Note:
5470   The index sets map from row/col of permuted matrix to row/col of original matrix.
5471   The index sets should be on the same communicator as mat and have the same local sizes.
5472 
5473   Developer Note:
5474   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5475   exploit the fact that row and col are permutations, consider implementing the
5476   more general `MatCreateSubMatrix()` instead.
5477 
5478 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5479 @*/
5480 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5481 {
5482   PetscFunctionBegin;
5483   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5484   PetscValidType(mat, 1);
5485   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5486   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5487   PetscAssertPointer(B, 4);
5488   PetscCheckSameComm(mat, 1, row, 2);
5489   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5492   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5493   MatCheckPreallocated(mat, 1);
5494 
5495   if (mat->ops->permute) {
5496     PetscUseTypeMethod(mat, permute, row, col, B);
5497     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5498   } else {
5499     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5500   }
5501   PetscFunctionReturn(PETSC_SUCCESS);
5502 }
5503 
5504 /*@
5505   MatEqual - Compares two matrices.
5506 
5507   Collective
5508 
5509   Input Parameters:
5510 + A - the first matrix
5511 - B - the second matrix
5512 
5513   Output Parameter:
5514 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5515 
5516   Level: intermediate
5517 
5518 .seealso: [](ch_matrices), `Mat`
5519 @*/
5520 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5521 {
5522   PetscFunctionBegin;
5523   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5524   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5525   PetscValidType(A, 1);
5526   PetscValidType(B, 2);
5527   PetscAssertPointer(flg, 3);
5528   PetscCheckSameComm(A, 1, B, 2);
5529   MatCheckPreallocated(A, 1);
5530   MatCheckPreallocated(B, 2);
5531   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5532   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5533   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,
5534              B->cmap->N);
5535   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5536     PetscUseTypeMethod(A, equal, B, flg);
5537   } else {
5538     PetscCall(MatMultEqual(A, B, 10, flg));
5539   }
5540   PetscFunctionReturn(PETSC_SUCCESS);
5541 }
5542 
5543 /*@
5544   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5545   matrices that are stored as vectors.  Either of the two scaling
5546   matrices can be `NULL`.
5547 
5548   Collective
5549 
5550   Input Parameters:
5551 + mat - the matrix to be scaled
5552 . l   - the left scaling vector (or `NULL`)
5553 - r   - the right scaling vector (or `NULL`)
5554 
5555   Level: intermediate
5556 
5557   Note:
5558   `MatDiagonalScale()` computes $A = LAR$, where
5559   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5560   The L scales the rows of the matrix, the R scales the columns of the matrix.
5561 
5562 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5563 @*/
5564 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5565 {
5566   PetscFunctionBegin;
5567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5568   PetscValidType(mat, 1);
5569   if (l) {
5570     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5571     PetscCheckSameComm(mat, 1, l, 2);
5572   }
5573   if (r) {
5574     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5575     PetscCheckSameComm(mat, 1, r, 3);
5576   }
5577   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5578   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5579   MatCheckPreallocated(mat, 1);
5580   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5581 
5582   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5583   PetscUseTypeMethod(mat, diagonalscale, l, r);
5584   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5585   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5586   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5587   PetscFunctionReturn(PETSC_SUCCESS);
5588 }
5589 
5590 /*@
5591   MatScale - Scales all elements of a matrix by a given number.
5592 
5593   Logically Collective
5594 
5595   Input Parameters:
5596 + mat - the matrix to be scaled
5597 - a   - the scaling value
5598 
5599   Level: intermediate
5600 
5601 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5602 @*/
5603 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5604 {
5605   PetscFunctionBegin;
5606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5607   PetscValidType(mat, 1);
5608   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5609   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5610   PetscValidLogicalCollectiveScalar(mat, a, 2);
5611   MatCheckPreallocated(mat, 1);
5612 
5613   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5614   if (a != (PetscScalar)1.0) {
5615     PetscUseTypeMethod(mat, scale, a);
5616     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5617   }
5618   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5619   PetscFunctionReturn(PETSC_SUCCESS);
5620 }
5621 
5622 /*@
5623   MatNorm - Calculates various norms of a matrix.
5624 
5625   Collective
5626 
5627   Input Parameters:
5628 + mat  - the matrix
5629 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5630 
5631   Output Parameter:
5632 . nrm - the resulting norm
5633 
5634   Level: intermediate
5635 
5636 .seealso: [](ch_matrices), `Mat`
5637 @*/
5638 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5639 {
5640   PetscFunctionBegin;
5641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5642   PetscValidType(mat, 1);
5643   PetscAssertPointer(nrm, 3);
5644 
5645   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5646   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5647   MatCheckPreallocated(mat, 1);
5648 
5649   PetscUseTypeMethod(mat, norm, type, nrm);
5650   PetscFunctionReturn(PETSC_SUCCESS);
5651 }
5652 
5653 /*
5654      This variable is used to prevent counting of MatAssemblyBegin() that
5655    are called from within a MatAssemblyEnd().
5656 */
5657 static PetscInt MatAssemblyEnd_InUse = 0;
5658 /*@
5659   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5660   be called after completing all calls to `MatSetValues()`.
5661 
5662   Collective
5663 
5664   Input Parameters:
5665 + mat  - the matrix
5666 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5667 
5668   Level: beginner
5669 
5670   Notes:
5671   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5672   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5673 
5674   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5675   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5676   using the matrix.
5677 
5678   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5679   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
5680   a global collective operation requiring all processes that share the matrix.
5681 
5682   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5683   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5684   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5685 
5686 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5687 @*/
5688 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5689 {
5690   PetscFunctionBegin;
5691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5692   PetscValidType(mat, 1);
5693   MatCheckPreallocated(mat, 1);
5694   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5695   if (mat->assembled) {
5696     mat->was_assembled = PETSC_TRUE;
5697     mat->assembled     = PETSC_FALSE;
5698   }
5699 
5700   if (!MatAssemblyEnd_InUse) {
5701     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5702     PetscTryTypeMethod(mat, assemblybegin, type);
5703     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5704   } else PetscTryTypeMethod(mat, assemblybegin, type);
5705   PetscFunctionReturn(PETSC_SUCCESS);
5706 }
5707 
5708 /*@
5709   MatAssembled - Indicates if a matrix has been assembled and is ready for
5710   use; for example, in matrix-vector product.
5711 
5712   Not Collective
5713 
5714   Input Parameter:
5715 . mat - the matrix
5716 
5717   Output Parameter:
5718 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5719 
5720   Level: advanced
5721 
5722 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5723 @*/
5724 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5725 {
5726   PetscFunctionBegin;
5727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5728   PetscAssertPointer(assembled, 2);
5729   *assembled = mat->assembled;
5730   PetscFunctionReturn(PETSC_SUCCESS);
5731 }
5732 
5733 /*@
5734   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5735   be called after `MatAssemblyBegin()`.
5736 
5737   Collective
5738 
5739   Input Parameters:
5740 + mat  - the matrix
5741 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5742 
5743   Options Database Keys:
5744 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5745 . -mat_view ::ascii_info_detail      - Prints more detailed info
5746 . -mat_view                          - Prints matrix in ASCII format
5747 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5748 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5749 . -display <name>                    - Sets display name (default is host)
5750 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5751 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5752 . -viewer_socket_machine <machine>   - Machine to use for socket
5753 . -viewer_socket_port <port>         - Port number to use for socket
5754 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5755 
5756   Level: beginner
5757 
5758 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5759 @*/
5760 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5761 {
5762   static PetscInt inassm = 0;
5763   PetscBool       flg    = PETSC_FALSE;
5764 
5765   PetscFunctionBegin;
5766   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5767   PetscValidType(mat, 1);
5768 
5769   inassm++;
5770   MatAssemblyEnd_InUse++;
5771   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5772     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5773     PetscTryTypeMethod(mat, assemblyend, type);
5774     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5775   } else PetscTryTypeMethod(mat, assemblyend, type);
5776 
5777   /* Flush assembly is not a true assembly */
5778   if (type != MAT_FLUSH_ASSEMBLY) {
5779     if (mat->num_ass) {
5780       if (!mat->symmetry_eternal) {
5781         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5782         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5783       }
5784       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5785       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5786     }
5787     mat->num_ass++;
5788     mat->assembled        = PETSC_TRUE;
5789     mat->ass_nonzerostate = mat->nonzerostate;
5790   }
5791 
5792   mat->insertmode = NOT_SET_VALUES;
5793   MatAssemblyEnd_InUse--;
5794   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5795   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5796     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5797 
5798     if (mat->checksymmetryonassembly) {
5799       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5800       if (flg) {
5801         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5802       } else {
5803         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5804       }
5805     }
5806     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5807   }
5808   inassm--;
5809   PetscFunctionReturn(PETSC_SUCCESS);
5810 }
5811 
5812 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5813 /*@
5814   MatSetOption - Sets a parameter option for a matrix. Some options
5815   may be specific to certain storage formats.  Some options
5816   determine how values will be inserted (or added). Sorted,
5817   row-oriented input will generally assemble the fastest. The default
5818   is row-oriented.
5819 
5820   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5821 
5822   Input Parameters:
5823 + mat - the matrix
5824 . op  - the option, one of those listed below (and possibly others),
5825 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5826 
5827   Options Describing Matrix Structure:
5828 + `MAT_SPD`                         - symmetric positive definite
5829 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5830 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5831 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5832 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5833 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5834 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5835 
5836    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5837    do not need to be computed (usually at a high cost)
5838 
5839    Options For Use with `MatSetValues()`:
5840    Insert a logically dense subblock, which can be
5841 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5842 
5843    These options reflect the data you pass in with `MatSetValues()`; it has
5844    nothing to do with how the data is stored internally in the matrix
5845    data structure.
5846 
5847    When (re)assembling a matrix, we can restrict the input for
5848    efficiency/debugging purposes.  These options include
5849 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5850 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5851 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5852 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5853 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5854 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5855         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5856         performance for very large process counts.
5857 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5858         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5859         functions, instead sending only neighbor messages.
5860 
5861   Level: intermediate
5862 
5863   Notes:
5864   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5865 
5866   Some options are relevant only for particular matrix types and
5867   are thus ignored by others.  Other options are not supported by
5868   certain matrix types and will generate an error message if set.
5869 
5870   If using Fortran to compute a matrix, one may need to
5871   use the column-oriented option (or convert to the row-oriented
5872   format).
5873 
5874   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5875   that would generate a new entry in the nonzero structure is instead
5876   ignored.  Thus, if memory has not already been allocated for this particular
5877   data, then the insertion is ignored. For dense matrices, in which
5878   the entire array is allocated, no entries are ever ignored.
5879   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5880 
5881   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5882   that would generate a new entry in the nonzero structure instead produces
5883   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
5884 
5885   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5886   that would generate a new entry that has not been preallocated will
5887   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5888   only.) This is a useful flag when debugging matrix memory preallocation.
5889   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5890 
5891   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5892   other processors should be dropped, rather than stashed.
5893   This is useful if you know that the "owning" processor is also
5894   always generating the correct matrix entries, so that PETSc need
5895   not transfer duplicate entries generated on another processor.
5896 
5897   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5898   searches during matrix assembly. When this flag is set, the hash table
5899   is created during the first matrix assembly. This hash table is
5900   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5901   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5902   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5903   supported by `MATMPIBAIJ` format only.
5904 
5905   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5906   are kept in the nonzero structure
5907 
5908   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5909   a zero location in the matrix
5910 
5911   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5912 
5913   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5914   zero row routines and thus improves performance for very large process counts.
5915 
5916   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5917   part of the matrix (since they should match the upper triangular part).
5918 
5919   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5920   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5921   with finite difference schemes with non-periodic boundary conditions.
5922 
5923   Developer Note:
5924   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5925   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5926   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5927   not changed.
5928 
5929 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5930 @*/
5931 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5932 {
5933   PetscFunctionBegin;
5934   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5935   if (op > 0) {
5936     PetscValidLogicalCollectiveEnum(mat, op, 2);
5937     PetscValidLogicalCollectiveBool(mat, flg, 3);
5938   }
5939 
5940   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);
5941 
5942   switch (op) {
5943   case MAT_FORCE_DIAGONAL_ENTRIES:
5944     mat->force_diagonals = flg;
5945     PetscFunctionReturn(PETSC_SUCCESS);
5946   case MAT_NO_OFF_PROC_ENTRIES:
5947     mat->nooffprocentries = flg;
5948     PetscFunctionReturn(PETSC_SUCCESS);
5949   case MAT_SUBSET_OFF_PROC_ENTRIES:
5950     mat->assembly_subset = flg;
5951     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5952 #if !defined(PETSC_HAVE_MPIUNI)
5953       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5954 #endif
5955       mat->stash.first_assembly_done = PETSC_FALSE;
5956     }
5957     PetscFunctionReturn(PETSC_SUCCESS);
5958   case MAT_NO_OFF_PROC_ZERO_ROWS:
5959     mat->nooffproczerorows = flg;
5960     PetscFunctionReturn(PETSC_SUCCESS);
5961   case MAT_SPD:
5962     if (flg) {
5963       mat->spd                    = PETSC_BOOL3_TRUE;
5964       mat->symmetric              = PETSC_BOOL3_TRUE;
5965       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5966     } else {
5967       mat->spd = PETSC_BOOL3_FALSE;
5968     }
5969     break;
5970   case MAT_SYMMETRIC:
5971     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5972     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5973 #if !defined(PETSC_USE_COMPLEX)
5974     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5975 #endif
5976     break;
5977   case MAT_HERMITIAN:
5978     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5979     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5980 #if !defined(PETSC_USE_COMPLEX)
5981     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5982 #endif
5983     break;
5984   case MAT_STRUCTURALLY_SYMMETRIC:
5985     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5986     break;
5987   case MAT_SYMMETRY_ETERNAL:
5988     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");
5989     mat->symmetry_eternal = flg;
5990     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5991     break;
5992   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5993     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");
5994     mat->structural_symmetry_eternal = flg;
5995     break;
5996   case MAT_SPD_ETERNAL:
5997     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");
5998     mat->spd_eternal = flg;
5999     if (flg) {
6000       mat->structural_symmetry_eternal = PETSC_TRUE;
6001       mat->symmetry_eternal            = PETSC_TRUE;
6002     }
6003     break;
6004   case MAT_STRUCTURE_ONLY:
6005     mat->structure_only = flg;
6006     break;
6007   case MAT_SORTED_FULL:
6008     mat->sortedfull = flg;
6009     break;
6010   default:
6011     break;
6012   }
6013   PetscTryTypeMethod(mat, setoption, op, flg);
6014   PetscFunctionReturn(PETSC_SUCCESS);
6015 }
6016 
6017 /*@
6018   MatGetOption - Gets a parameter option that has been set for a matrix.
6019 
6020   Logically Collective
6021 
6022   Input Parameters:
6023 + mat - the matrix
6024 - op  - the option, this only responds to certain options, check the code for which ones
6025 
6026   Output Parameter:
6027 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6028 
6029   Level: intermediate
6030 
6031   Notes:
6032   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6033 
6034   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6035   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6036 
6037 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6038     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6039 @*/
6040 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6041 {
6042   PetscFunctionBegin;
6043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6044   PetscValidType(mat, 1);
6045 
6046   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);
6047   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()");
6048 
6049   switch (op) {
6050   case MAT_NO_OFF_PROC_ENTRIES:
6051     *flg = mat->nooffprocentries;
6052     break;
6053   case MAT_NO_OFF_PROC_ZERO_ROWS:
6054     *flg = mat->nooffproczerorows;
6055     break;
6056   case MAT_SYMMETRIC:
6057     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6058     break;
6059   case MAT_HERMITIAN:
6060     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6061     break;
6062   case MAT_STRUCTURALLY_SYMMETRIC:
6063     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6064     break;
6065   case MAT_SPD:
6066     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6067     break;
6068   case MAT_SYMMETRY_ETERNAL:
6069     *flg = mat->symmetry_eternal;
6070     break;
6071   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6072     *flg = mat->symmetry_eternal;
6073     break;
6074   default:
6075     break;
6076   }
6077   PetscFunctionReturn(PETSC_SUCCESS);
6078 }
6079 
6080 /*@
6081   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6082   this routine retains the old nonzero structure.
6083 
6084   Logically Collective
6085 
6086   Input Parameter:
6087 . mat - the matrix
6088 
6089   Level: intermediate
6090 
6091   Note:
6092   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.
6093   See the Performance chapter of the users manual for information on preallocating matrices.
6094 
6095 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6096 @*/
6097 PetscErrorCode MatZeroEntries(Mat mat)
6098 {
6099   PetscFunctionBegin;
6100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6101   PetscValidType(mat, 1);
6102   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6103   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");
6104   MatCheckPreallocated(mat, 1);
6105 
6106   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6107   PetscUseTypeMethod(mat, zeroentries);
6108   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6109   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6110   PetscFunctionReturn(PETSC_SUCCESS);
6111 }
6112 
6113 /*@
6114   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6115   of a set of rows and columns of a matrix.
6116 
6117   Collective
6118 
6119   Input Parameters:
6120 + mat     - the matrix
6121 . numRows - the number of rows/columns to zero
6122 . rows    - the global row indices
6123 . diag    - value put in the diagonal of the eliminated rows
6124 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6125 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6126 
6127   Level: intermediate
6128 
6129   Notes:
6130   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6131 
6132   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6133   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
6134 
6135   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6136   Krylov method to take advantage of the known solution on the zeroed rows.
6137 
6138   For the parallel case, all processes that share the matrix (i.e.,
6139   those in the communicator used for matrix creation) MUST call this
6140   routine, regardless of whether any rows being zeroed are owned by
6141   them.
6142 
6143   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6144 
6145   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6146   list only rows local to itself).
6147 
6148   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6149 
6150 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6151           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6152 @*/
6153 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6154 {
6155   PetscFunctionBegin;
6156   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6157   PetscValidType(mat, 1);
6158   if (numRows) PetscAssertPointer(rows, 3);
6159   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6160   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6161   MatCheckPreallocated(mat, 1);
6162 
6163   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6164   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6165   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6166   PetscFunctionReturn(PETSC_SUCCESS);
6167 }
6168 
6169 /*@
6170   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6171   of a set of rows and columns of a matrix.
6172 
6173   Collective
6174 
6175   Input Parameters:
6176 + mat  - the matrix
6177 . is   - the rows to zero
6178 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6179 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6180 - b    - optional vector of right hand side, that will be adjusted by provided solution
6181 
6182   Level: intermediate
6183 
6184   Note:
6185   See `MatZeroRowsColumns()` for details on how this routine operates.
6186 
6187 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6188           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6189 @*/
6190 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6191 {
6192   PetscInt        numRows;
6193   const PetscInt *rows;
6194 
6195   PetscFunctionBegin;
6196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6197   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6198   PetscValidType(mat, 1);
6199   PetscValidType(is, 2);
6200   PetscCall(ISGetLocalSize(is, &numRows));
6201   PetscCall(ISGetIndices(is, &rows));
6202   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6203   PetscCall(ISRestoreIndices(is, &rows));
6204   PetscFunctionReturn(PETSC_SUCCESS);
6205 }
6206 
6207 /*@
6208   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6209   of a set of rows of a matrix.
6210 
6211   Collective
6212 
6213   Input Parameters:
6214 + mat     - the matrix
6215 . numRows - the number of rows to zero
6216 . rows    - the global row indices
6217 . diag    - value put in the diagonal of the zeroed rows
6218 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6219 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6220 
6221   Level: intermediate
6222 
6223   Notes:
6224   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6225 
6226   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6227 
6228   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6229   Krylov method to take advantage of the known solution on the zeroed rows.
6230 
6231   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)
6232   from the matrix.
6233 
6234   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6235   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
6236   formats this does not alter the nonzero structure.
6237 
6238   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6239   of the matrix is not changed the values are
6240   merely zeroed.
6241 
6242   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6243   formats can optionally remove the main diagonal entry from the
6244   nonzero structure as well, by passing 0.0 as the final argument).
6245 
6246   For the parallel case, all processes that share the matrix (i.e.,
6247   those in the communicator used for matrix creation) MUST call this
6248   routine, regardless of whether any rows being zeroed are owned by
6249   them.
6250 
6251   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6252   list only rows local to itself).
6253 
6254   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6255   owns that are to be zeroed. This saves a global synchronization in the implementation.
6256 
6257 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6258           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6259 @*/
6260 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6261 {
6262   PetscFunctionBegin;
6263   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6264   PetscValidType(mat, 1);
6265   if (numRows) PetscAssertPointer(rows, 3);
6266   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6267   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6268   MatCheckPreallocated(mat, 1);
6269 
6270   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6271   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6272   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6273   PetscFunctionReturn(PETSC_SUCCESS);
6274 }
6275 
6276 /*@
6277   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6278   of a set of rows of a matrix.
6279 
6280   Collective
6281 
6282   Input Parameters:
6283 + mat  - the matrix
6284 . is   - index set of rows to remove (if `NULL` then no row is removed)
6285 . diag - value put in all diagonals of eliminated rows
6286 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6287 - b    - optional vector of right hand side, that will be adjusted by provided solution
6288 
6289   Level: intermediate
6290 
6291   Note:
6292   See `MatZeroRows()` for details on how this routine operates.
6293 
6294 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6295           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6296 @*/
6297 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6298 {
6299   PetscInt        numRows = 0;
6300   const PetscInt *rows    = NULL;
6301 
6302   PetscFunctionBegin;
6303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6304   PetscValidType(mat, 1);
6305   if (is) {
6306     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6307     PetscCall(ISGetLocalSize(is, &numRows));
6308     PetscCall(ISGetIndices(is, &rows));
6309   }
6310   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6311   if (is) PetscCall(ISRestoreIndices(is, &rows));
6312   PetscFunctionReturn(PETSC_SUCCESS);
6313 }
6314 
6315 /*@
6316   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6317   of a set of rows of a matrix. These rows must be local to the process.
6318 
6319   Collective
6320 
6321   Input Parameters:
6322 + mat     - the matrix
6323 . numRows - the number of rows to remove
6324 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6325 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6326 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6327 - b       - optional vector of right hand side, that will be adjusted by provided solution
6328 
6329   Level: intermediate
6330 
6331   Notes:
6332   See `MatZeroRows()` for details on how this routine operates.
6333 
6334   The grid coordinates are across the entire grid, not just the local portion
6335 
6336   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6337   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6338   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6339   `DM_BOUNDARY_PERIODIC` boundary type.
6340 
6341   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
6342   a single value per point) you can skip filling those indices.
6343 
6344   Fortran Note:
6345   `idxm` and `idxn` should be declared as
6346 $     MatStencil idxm(4, m)
6347   and the values inserted using
6348 .vb
6349     idxm(MatStencil_i, 1) = i
6350     idxm(MatStencil_j, 1) = j
6351     idxm(MatStencil_k, 1) = k
6352     idxm(MatStencil_c, 1) = c
6353    etc
6354 .ve
6355 
6356 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6357           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6358 @*/
6359 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6360 {
6361   PetscInt  dim    = mat->stencil.dim;
6362   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6363   PetscInt *dims   = mat->stencil.dims + 1;
6364   PetscInt *starts = mat->stencil.starts;
6365   PetscInt *dxm    = (PetscInt *)rows;
6366   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6367 
6368   PetscFunctionBegin;
6369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6370   PetscValidType(mat, 1);
6371   if (numRows) PetscAssertPointer(rows, 3);
6372 
6373   PetscCall(PetscMalloc1(numRows, &jdxm));
6374   for (i = 0; i < numRows; ++i) {
6375     /* Skip unused dimensions (they are ordered k, j, i, c) */
6376     for (j = 0; j < 3 - sdim; ++j) dxm++;
6377     /* Local index in X dir */
6378     tmp = *dxm++ - starts[0];
6379     /* Loop over remaining dimensions */
6380     for (j = 0; j < dim - 1; ++j) {
6381       /* If nonlocal, set index to be negative */
6382       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6383       /* Update local index */
6384       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6385     }
6386     /* Skip component slot if necessary */
6387     if (mat->stencil.noc) dxm++;
6388     /* Local row number */
6389     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6390   }
6391   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6392   PetscCall(PetscFree(jdxm));
6393   PetscFunctionReturn(PETSC_SUCCESS);
6394 }
6395 
6396 /*@
6397   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6398   of a set of rows and columns of a matrix.
6399 
6400   Collective
6401 
6402   Input Parameters:
6403 + mat     - the matrix
6404 . numRows - the number of rows/columns to remove
6405 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6406 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6407 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6408 - b       - optional vector of right hand side, that will be adjusted by provided solution
6409 
6410   Level: intermediate
6411 
6412   Notes:
6413   See `MatZeroRowsColumns()` for details on how this routine operates.
6414 
6415   The grid coordinates are across the entire grid, not just the local portion
6416 
6417   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6418   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6419   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6420   `DM_BOUNDARY_PERIODIC` boundary type.
6421 
6422   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
6423   a single value per point) you can skip filling those indices.
6424 
6425   Fortran Note:
6426   `idxm` and `idxn` should be declared as
6427 $     MatStencil idxm(4, m)
6428   and the values inserted using
6429 .vb
6430     idxm(MatStencil_i, 1) = i
6431     idxm(MatStencil_j, 1) = j
6432     idxm(MatStencil_k, 1) = k
6433     idxm(MatStencil_c, 1) = c
6434     etc
6435 .ve
6436 
6437 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6438           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6439 @*/
6440 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6441 {
6442   PetscInt  dim    = mat->stencil.dim;
6443   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6444   PetscInt *dims   = mat->stencil.dims + 1;
6445   PetscInt *starts = mat->stencil.starts;
6446   PetscInt *dxm    = (PetscInt *)rows;
6447   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6448 
6449   PetscFunctionBegin;
6450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6451   PetscValidType(mat, 1);
6452   if (numRows) PetscAssertPointer(rows, 3);
6453 
6454   PetscCall(PetscMalloc1(numRows, &jdxm));
6455   for (i = 0; i < numRows; ++i) {
6456     /* Skip unused dimensions (they are ordered k, j, i, c) */
6457     for (j = 0; j < 3 - sdim; ++j) dxm++;
6458     /* Local index in X dir */
6459     tmp = *dxm++ - starts[0];
6460     /* Loop over remaining dimensions */
6461     for (j = 0; j < dim - 1; ++j) {
6462       /* If nonlocal, set index to be negative */
6463       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6464       /* Update local index */
6465       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6466     }
6467     /* Skip component slot if necessary */
6468     if (mat->stencil.noc) dxm++;
6469     /* Local row number */
6470     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6471   }
6472   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6473   PetscCall(PetscFree(jdxm));
6474   PetscFunctionReturn(PETSC_SUCCESS);
6475 }
6476 
6477 /*@C
6478   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6479   of a set of rows of a matrix; using local numbering of rows.
6480 
6481   Collective
6482 
6483   Input Parameters:
6484 + mat     - the matrix
6485 . numRows - the number of rows to remove
6486 . rows    - the local row indices
6487 . diag    - value put in all diagonals of eliminated rows
6488 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6489 - b       - optional vector of right hand side, that will be adjusted by provided solution
6490 
6491   Level: intermediate
6492 
6493   Notes:
6494   Before calling `MatZeroRowsLocal()`, the user must first set the
6495   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6496 
6497   See `MatZeroRows()` for details on how this routine operates.
6498 
6499 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6500           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6501 @*/
6502 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6503 {
6504   PetscFunctionBegin;
6505   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6506   PetscValidType(mat, 1);
6507   if (numRows) PetscAssertPointer(rows, 3);
6508   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6509   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6510   MatCheckPreallocated(mat, 1);
6511 
6512   if (mat->ops->zerorowslocal) {
6513     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6514   } else {
6515     IS              is, newis;
6516     const PetscInt *newRows;
6517 
6518     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6519     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6520     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6521     PetscCall(ISGetIndices(newis, &newRows));
6522     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6523     PetscCall(ISRestoreIndices(newis, &newRows));
6524     PetscCall(ISDestroy(&newis));
6525     PetscCall(ISDestroy(&is));
6526   }
6527   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6528   PetscFunctionReturn(PETSC_SUCCESS);
6529 }
6530 
6531 /*@
6532   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6533   of a set of rows of a matrix; using local numbering of rows.
6534 
6535   Collective
6536 
6537   Input Parameters:
6538 + mat  - the matrix
6539 . is   - index set of rows to remove
6540 . diag - value put in all diagonals of eliminated rows
6541 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6542 - b    - optional vector of right hand side, that will be adjusted by provided solution
6543 
6544   Level: intermediate
6545 
6546   Notes:
6547   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6548   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6549 
6550   See `MatZeroRows()` for details on how this routine operates.
6551 
6552 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6553           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6554 @*/
6555 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6556 {
6557   PetscInt        numRows;
6558   const PetscInt *rows;
6559 
6560   PetscFunctionBegin;
6561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6562   PetscValidType(mat, 1);
6563   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6564   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6565   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6566   MatCheckPreallocated(mat, 1);
6567 
6568   PetscCall(ISGetLocalSize(is, &numRows));
6569   PetscCall(ISGetIndices(is, &rows));
6570   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6571   PetscCall(ISRestoreIndices(is, &rows));
6572   PetscFunctionReturn(PETSC_SUCCESS);
6573 }
6574 
6575 /*@
6576   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6577   of a set of rows and columns of a matrix; using local numbering of rows.
6578 
6579   Collective
6580 
6581   Input Parameters:
6582 + mat     - the matrix
6583 . numRows - the number of rows to remove
6584 . rows    - the global row indices
6585 . diag    - value put in all diagonals of eliminated rows
6586 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6587 - b       - optional vector of right hand side, that will be adjusted by provided solution
6588 
6589   Level: intermediate
6590 
6591   Notes:
6592   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6593   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6594 
6595   See `MatZeroRowsColumns()` for details on how this routine operates.
6596 
6597 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6598           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6599 @*/
6600 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6601 {
6602   IS              is, newis;
6603   const PetscInt *newRows;
6604 
6605   PetscFunctionBegin;
6606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6607   PetscValidType(mat, 1);
6608   if (numRows) PetscAssertPointer(rows, 3);
6609   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6610   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6611   MatCheckPreallocated(mat, 1);
6612 
6613   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6614   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6615   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6616   PetscCall(ISGetIndices(newis, &newRows));
6617   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6618   PetscCall(ISRestoreIndices(newis, &newRows));
6619   PetscCall(ISDestroy(&newis));
6620   PetscCall(ISDestroy(&is));
6621   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6622   PetscFunctionReturn(PETSC_SUCCESS);
6623 }
6624 
6625 /*@
6626   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6627   of a set of rows and columns of a matrix; using local numbering of rows.
6628 
6629   Collective
6630 
6631   Input Parameters:
6632 + mat  - the matrix
6633 . is   - index set of rows to remove
6634 . diag - value put in all diagonals of eliminated rows
6635 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6636 - b    - optional vector of right hand side, that will be adjusted by provided solution
6637 
6638   Level: intermediate
6639 
6640   Notes:
6641   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6642   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6643 
6644   See `MatZeroRowsColumns()` for details on how this routine operates.
6645 
6646 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6647           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6648 @*/
6649 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6650 {
6651   PetscInt        numRows;
6652   const PetscInt *rows;
6653 
6654   PetscFunctionBegin;
6655   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6656   PetscValidType(mat, 1);
6657   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6658   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6659   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6660   MatCheckPreallocated(mat, 1);
6661 
6662   PetscCall(ISGetLocalSize(is, &numRows));
6663   PetscCall(ISGetIndices(is, &rows));
6664   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6665   PetscCall(ISRestoreIndices(is, &rows));
6666   PetscFunctionReturn(PETSC_SUCCESS);
6667 }
6668 
6669 /*@C
6670   MatGetSize - Returns the numbers of rows and columns in a matrix.
6671 
6672   Not Collective
6673 
6674   Input Parameter:
6675 . mat - the matrix
6676 
6677   Output Parameters:
6678 + m - the number of global rows
6679 - n - the number of global columns
6680 
6681   Level: beginner
6682 
6683   Note:
6684   Both output parameters can be `NULL` on input.
6685 
6686 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6687 @*/
6688 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6689 {
6690   PetscFunctionBegin;
6691   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6692   if (m) *m = mat->rmap->N;
6693   if (n) *n = mat->cmap->N;
6694   PetscFunctionReturn(PETSC_SUCCESS);
6695 }
6696 
6697 /*@C
6698   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6699   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6700 
6701   Not Collective
6702 
6703   Input Parameter:
6704 . mat - the matrix
6705 
6706   Output Parameters:
6707 + m - the number of local rows, use `NULL` to not obtain this value
6708 - n - the number of local columns, use `NULL` to not obtain this value
6709 
6710   Level: beginner
6711 
6712 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6713 @*/
6714 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6715 {
6716   PetscFunctionBegin;
6717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6718   if (m) PetscAssertPointer(m, 2);
6719   if (n) PetscAssertPointer(n, 3);
6720   if (m) *m = mat->rmap->n;
6721   if (n) *n = mat->cmap->n;
6722   PetscFunctionReturn(PETSC_SUCCESS);
6723 }
6724 
6725 /*@C
6726   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6727   vector one multiplies this matrix by that are owned by this processor.
6728 
6729   Not Collective, unless matrix has not been allocated, then collective
6730 
6731   Input Parameter:
6732 . mat - the matrix
6733 
6734   Output Parameters:
6735 + m - the global index of the first local column, use `NULL` to not obtain this value
6736 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6737 
6738   Level: developer
6739 
6740   Note:
6741   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6742   Layouts](sec_matlayout) for details on matrix layouts.
6743 
6744 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6745 @*/
6746 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6747 {
6748   PetscFunctionBegin;
6749   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6750   PetscValidType(mat, 1);
6751   if (m) PetscAssertPointer(m, 2);
6752   if (n) PetscAssertPointer(n, 3);
6753   MatCheckPreallocated(mat, 1);
6754   if (m) *m = mat->cmap->rstart;
6755   if (n) *n = mat->cmap->rend;
6756   PetscFunctionReturn(PETSC_SUCCESS);
6757 }
6758 
6759 /*@C
6760   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6761   this MPI process.
6762 
6763   Not Collective
6764 
6765   Input Parameter:
6766 . mat - the matrix
6767 
6768   Output Parameters:
6769 + m - the global index of the first local row, use `NULL` to not obtain this value
6770 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6771 
6772   Level: beginner
6773 
6774   Note:
6775   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6776   would contain the result of a matrix vector product with this matrix. See [Matrix
6777   Layouts](sec_matlayout) for details on matrix layouts.
6778 
6779 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6780           `PetscLayout`
6781 @*/
6782 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6783 {
6784   PetscFunctionBegin;
6785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6786   PetscValidType(mat, 1);
6787   if (m) PetscAssertPointer(m, 2);
6788   if (n) PetscAssertPointer(n, 3);
6789   MatCheckPreallocated(mat, 1);
6790   if (m) *m = mat->rmap->rstart;
6791   if (n) *n = mat->rmap->rend;
6792   PetscFunctionReturn(PETSC_SUCCESS);
6793 }
6794 
6795 /*@C
6796   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6797   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6798 
6799   Not Collective, unless matrix has not been allocated
6800 
6801   Input Parameter:
6802 . mat - the matrix
6803 
6804   Output Parameter:
6805 . ranges - start of each processors portion plus one more than the total length at the end
6806 
6807   Level: beginner
6808 
6809   Note:
6810   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6811   would contain the result of a matrix vector product with this matrix. See [Matrix
6812   Layouts](sec_matlayout) for details on matrix layouts.
6813 
6814 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6815 @*/
6816 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6817 {
6818   PetscFunctionBegin;
6819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6820   PetscValidType(mat, 1);
6821   MatCheckPreallocated(mat, 1);
6822   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6823   PetscFunctionReturn(PETSC_SUCCESS);
6824 }
6825 
6826 /*@C
6827   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6828   vector one multiplies this vector by that are owned by each processor.
6829 
6830   Not Collective, unless matrix has not been allocated
6831 
6832   Input Parameter:
6833 . mat - the matrix
6834 
6835   Output Parameter:
6836 . ranges - start of each processors portion plus one more than the total length at the end
6837 
6838   Level: beginner
6839 
6840   Note:
6841   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6842   Layouts](sec_matlayout) for details on matrix layouts.
6843 
6844 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6845 @*/
6846 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6847 {
6848   PetscFunctionBegin;
6849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6850   PetscValidType(mat, 1);
6851   MatCheckPreallocated(mat, 1);
6852   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6853   PetscFunctionReturn(PETSC_SUCCESS);
6854 }
6855 
6856 /*@C
6857   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6858 
6859   Not Collective
6860 
6861   Input Parameter:
6862 . A - matrix
6863 
6864   Output Parameters:
6865 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6866 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6867 
6868   Level: intermediate
6869 
6870   Note:
6871   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6872   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6873   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6874   details on matrix layouts.
6875 
6876 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6877 @*/
6878 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6879 {
6880   PetscErrorCode (*f)(Mat, IS *, IS *);
6881 
6882   PetscFunctionBegin;
6883   MatCheckPreallocated(A, 1);
6884   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6885   if (f) {
6886     PetscCall((*f)(A, rows, cols));
6887   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6888     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6889     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6890   }
6891   PetscFunctionReturn(PETSC_SUCCESS);
6892 }
6893 
6894 /*@C
6895   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6896   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6897   to complete the factorization.
6898 
6899   Collective
6900 
6901   Input Parameters:
6902 + fact - the factorized matrix obtained with `MatGetFactor()`
6903 . mat  - the matrix
6904 . row  - row permutation
6905 . col  - column permutation
6906 - info - structure containing
6907 .vb
6908       levels - number of levels of fill.
6909       expected fill - as ratio of original fill.
6910       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6911                 missing diagonal entries)
6912 .ve
6913 
6914   Level: developer
6915 
6916   Notes:
6917   See [Matrix Factorization](sec_matfactor) for additional information.
6918 
6919   Most users should employ the `KSP` interface for linear solvers
6920   instead of working directly with matrix algebra routines such as this.
6921   See, e.g., `KSPCreate()`.
6922 
6923   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
6924 
6925   Developer Note:
6926   The Fortran interface is not autogenerated as the
6927   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6928 
6929 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6930           `MatGetOrdering()`, `MatFactorInfo`
6931 @*/
6932 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6933 {
6934   PetscFunctionBegin;
6935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6936   PetscValidType(mat, 2);
6937   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6938   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6939   PetscAssertPointer(info, 5);
6940   PetscAssertPointer(fact, 1);
6941   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6942   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6943   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6944   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6945   MatCheckPreallocated(mat, 2);
6946 
6947   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6948   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6949   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6950   PetscFunctionReturn(PETSC_SUCCESS);
6951 }
6952 
6953 /*@C
6954   MatICCFactorSymbolic - Performs symbolic incomplete
6955   Cholesky factorization for a symmetric matrix.  Use
6956   `MatCholeskyFactorNumeric()` to complete the factorization.
6957 
6958   Collective
6959 
6960   Input Parameters:
6961 + fact - the factorized matrix obtained with `MatGetFactor()`
6962 . mat  - the matrix to be factored
6963 . perm - row and column permutation
6964 - info - structure containing
6965 .vb
6966       levels - number of levels of fill.
6967       expected fill - as ratio of original fill.
6968 .ve
6969 
6970   Level: developer
6971 
6972   Notes:
6973   Most users should employ the `KSP` interface for linear solvers
6974   instead of working directly with matrix algebra routines such as this.
6975   See, e.g., `KSPCreate()`.
6976 
6977   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
6978 
6979   Developer Note:
6980   The Fortran interface is not autogenerated as the
6981   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6982 
6983 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6984 @*/
6985 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6986 {
6987   PetscFunctionBegin;
6988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6989   PetscValidType(mat, 2);
6990   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6991   PetscAssertPointer(info, 4);
6992   PetscAssertPointer(fact, 1);
6993   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6994   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6995   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6996   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6997   MatCheckPreallocated(mat, 2);
6998 
6999   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7000   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7001   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7002   PetscFunctionReturn(PETSC_SUCCESS);
7003 }
7004 
7005 /*@C
7006   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7007   points to an array of valid matrices, they may be reused to store the new
7008   submatrices.
7009 
7010   Collective
7011 
7012   Input Parameters:
7013 + mat   - the matrix
7014 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7015 . irow  - index set of rows to extract
7016 . icol  - index set of columns to extract
7017 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7018 
7019   Output Parameter:
7020 . submat - the array of submatrices
7021 
7022   Level: advanced
7023 
7024   Notes:
7025   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7026   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7027   to extract a parallel submatrix.
7028 
7029   Some matrix types place restrictions on the row and column
7030   indices, such as that they be sorted or that they be equal to each other.
7031 
7032   The index sets may not have duplicate entries.
7033 
7034   When extracting submatrices from a parallel matrix, each processor can
7035   form a different submatrix by setting the rows and columns of its
7036   individual index sets according to the local submatrix desired.
7037 
7038   When finished using the submatrices, the user should destroy
7039   them with `MatDestroySubMatrices()`.
7040 
7041   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7042   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7043 
7044   This routine creates the matrices in submat; you should NOT create them before
7045   calling it. It also allocates the array of matrix pointers submat.
7046 
7047   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7048   request one row/column in a block, they must request all rows/columns that are in
7049   that block. For example, if the block size is 2 you cannot request just row 0 and
7050   column 0.
7051 
7052   Fortran Note:
7053   The Fortran interface is slightly different from that given below; it
7054   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7055 
7056 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7057 @*/
7058 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7059 {
7060   PetscInt  i;
7061   PetscBool eq;
7062 
7063   PetscFunctionBegin;
7064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7065   PetscValidType(mat, 1);
7066   if (n) {
7067     PetscAssertPointer(irow, 3);
7068     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7069     PetscAssertPointer(icol, 4);
7070     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7071   }
7072   PetscAssertPointer(submat, 6);
7073   if (n && scall == MAT_REUSE_MATRIX) {
7074     PetscAssertPointer(*submat, 6);
7075     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7076   }
7077   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7078   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7079   MatCheckPreallocated(mat, 1);
7080   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7081   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7082   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7083   for (i = 0; i < n; i++) {
7084     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7085     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7086     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7087 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7088     if (mat->boundtocpu && mat->bindingpropagates) {
7089       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7090       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7091     }
7092 #endif
7093   }
7094   PetscFunctionReturn(PETSC_SUCCESS);
7095 }
7096 
7097 /*@C
7098   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7099 
7100   Collective
7101 
7102   Input Parameters:
7103 + mat   - the matrix
7104 . n     - the number of submatrixes to be extracted
7105 . irow  - index set of rows to extract
7106 . icol  - index set of columns to extract
7107 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7108 
7109   Output Parameter:
7110 . submat - the array of submatrices
7111 
7112   Level: advanced
7113 
7114   Note:
7115   This is used by `PCGASM`
7116 
7117 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7118 @*/
7119 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7120 {
7121   PetscInt  i;
7122   PetscBool eq;
7123 
7124   PetscFunctionBegin;
7125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7126   PetscValidType(mat, 1);
7127   if (n) {
7128     PetscAssertPointer(irow, 3);
7129     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7130     PetscAssertPointer(icol, 4);
7131     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7132   }
7133   PetscAssertPointer(submat, 6);
7134   if (n && scall == MAT_REUSE_MATRIX) {
7135     PetscAssertPointer(*submat, 6);
7136     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7137   }
7138   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7139   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7140   MatCheckPreallocated(mat, 1);
7141 
7142   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7143   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7144   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7145   for (i = 0; i < n; i++) {
7146     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7147     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7148   }
7149   PetscFunctionReturn(PETSC_SUCCESS);
7150 }
7151 
7152 /*@C
7153   MatDestroyMatrices - Destroys an array of matrices.
7154 
7155   Collective
7156 
7157   Input Parameters:
7158 + n   - the number of local matrices
7159 - mat - the matrices (this is a pointer to the array of matrices)
7160 
7161   Level: advanced
7162 
7163   Note:
7164   Frees not only the matrices, but also the array that contains the matrices
7165 
7166   Fortran Note:
7167   This does not free the array.
7168 
7169 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7170 @*/
7171 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7172 {
7173   PetscInt i;
7174 
7175   PetscFunctionBegin;
7176   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7177   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7178   PetscAssertPointer(mat, 2);
7179 
7180   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7181 
7182   /* memory is allocated even if n = 0 */
7183   PetscCall(PetscFree(*mat));
7184   PetscFunctionReturn(PETSC_SUCCESS);
7185 }
7186 
7187 /*@C
7188   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7189 
7190   Collective
7191 
7192   Input Parameters:
7193 + n   - the number of local matrices
7194 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7195                        sequence of `MatCreateSubMatrices()`)
7196 
7197   Level: advanced
7198 
7199   Note:
7200   Frees not only the matrices, but also the array that contains the matrices
7201 
7202   Fortran Note:
7203   This does not free the array.
7204 
7205 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7206 @*/
7207 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7208 {
7209   Mat mat0;
7210 
7211   PetscFunctionBegin;
7212   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7213   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7214   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7215   PetscAssertPointer(mat, 2);
7216 
7217   mat0 = (*mat)[0];
7218   if (mat0 && mat0->ops->destroysubmatrices) {
7219     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7220   } else {
7221     PetscCall(MatDestroyMatrices(n, mat));
7222   }
7223   PetscFunctionReturn(PETSC_SUCCESS);
7224 }
7225 
7226 /*@C
7227   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7228 
7229   Collective
7230 
7231   Input Parameter:
7232 . mat - the matrix
7233 
7234   Output Parameter:
7235 . matstruct - the sequential matrix with the nonzero structure of mat
7236 
7237   Level: developer
7238 
7239 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7240 @*/
7241 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7242 {
7243   PetscFunctionBegin;
7244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7245   PetscAssertPointer(matstruct, 2);
7246 
7247   PetscValidType(mat, 1);
7248   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7249   MatCheckPreallocated(mat, 1);
7250 
7251   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7252   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7253   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7254   PetscFunctionReturn(PETSC_SUCCESS);
7255 }
7256 
7257 /*@C
7258   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7259 
7260   Collective
7261 
7262   Input Parameter:
7263 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7264                        sequence of `MatGetSeqNonzeroStructure()`)
7265 
7266   Level: advanced
7267 
7268   Note:
7269   Frees not only the matrices, but also the array that contains the matrices
7270 
7271 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7272 @*/
7273 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7274 {
7275   PetscFunctionBegin;
7276   PetscAssertPointer(mat, 1);
7277   PetscCall(MatDestroy(mat));
7278   PetscFunctionReturn(PETSC_SUCCESS);
7279 }
7280 
7281 /*@
7282   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7283   replaces the index sets by larger ones that represent submatrices with
7284   additional overlap.
7285 
7286   Collective
7287 
7288   Input Parameters:
7289 + mat - the matrix
7290 . n   - the number of index sets
7291 . is  - the array of index sets (these index sets will changed during the call)
7292 - ov  - the additional overlap requested
7293 
7294   Options Database Key:
7295 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7296 
7297   Level: developer
7298 
7299   Note:
7300   The computed overlap preserves the matrix block sizes when the blocks are square.
7301   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7302   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7303 
7304 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7305 @*/
7306 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7307 {
7308   PetscInt i, bs, cbs;
7309 
7310   PetscFunctionBegin;
7311   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7312   PetscValidType(mat, 1);
7313   PetscValidLogicalCollectiveInt(mat, n, 2);
7314   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7315   if (n) {
7316     PetscAssertPointer(is, 3);
7317     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7318   }
7319   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7320   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7321   MatCheckPreallocated(mat, 1);
7322 
7323   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7324   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7325   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7326   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7327   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7328   if (bs == cbs) {
7329     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7330   }
7331   PetscFunctionReturn(PETSC_SUCCESS);
7332 }
7333 
7334 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7335 
7336 /*@
7337   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7338   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7339   additional overlap.
7340 
7341   Collective
7342 
7343   Input Parameters:
7344 + mat - the matrix
7345 . n   - the number of index sets
7346 . is  - the array of index sets (these index sets will changed during the call)
7347 - ov  - the additional overlap requested
7348 
7349   `   Options Database Key:
7350 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7351 
7352   Level: developer
7353 
7354 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7355 @*/
7356 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7357 {
7358   PetscInt i;
7359 
7360   PetscFunctionBegin;
7361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7362   PetscValidType(mat, 1);
7363   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7364   if (n) {
7365     PetscAssertPointer(is, 3);
7366     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7367   }
7368   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7369   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7370   MatCheckPreallocated(mat, 1);
7371   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7372   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7373   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7374   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7375   PetscFunctionReturn(PETSC_SUCCESS);
7376 }
7377 
7378 /*@
7379   MatGetBlockSize - Returns the matrix block size.
7380 
7381   Not Collective
7382 
7383   Input Parameter:
7384 . mat - the matrix
7385 
7386   Output Parameter:
7387 . bs - block size
7388 
7389   Level: intermediate
7390 
7391   Notes:
7392   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7393 
7394   If the block size has not been set yet this routine returns 1.
7395 
7396 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7397 @*/
7398 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7399 {
7400   PetscFunctionBegin;
7401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7402   PetscAssertPointer(bs, 2);
7403   *bs = PetscAbs(mat->rmap->bs);
7404   PetscFunctionReturn(PETSC_SUCCESS);
7405 }
7406 
7407 /*@
7408   MatGetBlockSizes - Returns the matrix block row and column sizes.
7409 
7410   Not Collective
7411 
7412   Input Parameter:
7413 . mat - the matrix
7414 
7415   Output Parameters:
7416 + rbs - row block size
7417 - cbs - column block size
7418 
7419   Level: intermediate
7420 
7421   Notes:
7422   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7423   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7424 
7425   If a block size has not been set yet this routine returns 1.
7426 
7427 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7428 @*/
7429 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7430 {
7431   PetscFunctionBegin;
7432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7433   if (rbs) PetscAssertPointer(rbs, 2);
7434   if (cbs) PetscAssertPointer(cbs, 3);
7435   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7436   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7437   PetscFunctionReturn(PETSC_SUCCESS);
7438 }
7439 
7440 /*@
7441   MatSetBlockSize - Sets the matrix block size.
7442 
7443   Logically Collective
7444 
7445   Input Parameters:
7446 + mat - the matrix
7447 - bs  - block size
7448 
7449   Level: intermediate
7450 
7451   Notes:
7452   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7453   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7454 
7455   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7456   is compatible with the matrix local sizes.
7457 
7458 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7459 @*/
7460 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7461 {
7462   PetscFunctionBegin;
7463   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7464   PetscValidLogicalCollectiveInt(mat, bs, 2);
7465   PetscCall(MatSetBlockSizes(mat, bs, bs));
7466   PetscFunctionReturn(PETSC_SUCCESS);
7467 }
7468 
7469 typedef struct {
7470   PetscInt         n;
7471   IS              *is;
7472   Mat             *mat;
7473   PetscObjectState nonzerostate;
7474   Mat              C;
7475 } EnvelopeData;
7476 
7477 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7478 {
7479   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7480   PetscCall(PetscFree(edata->is));
7481   PetscCall(PetscFree(edata));
7482   return PETSC_SUCCESS;
7483 }
7484 
7485 /*@
7486   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7487   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7488 
7489   Collective
7490 
7491   Input Parameter:
7492 . mat - the matrix
7493 
7494   Level: intermediate
7495 
7496   Notes:
7497   There can be zeros within the blocks
7498 
7499   The blocks can overlap between processes, including laying on more than two processes
7500 
7501 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7502 @*/
7503 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7504 {
7505   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7506   PetscInt          *diag, *odiag, sc;
7507   VecScatter         scatter;
7508   PetscScalar       *seqv;
7509   const PetscScalar *parv;
7510   const PetscInt    *ia, *ja;
7511   PetscBool          set, flag, done;
7512   Mat                AA = mat, A;
7513   MPI_Comm           comm;
7514   PetscMPIInt        rank, size, tag;
7515   MPI_Status         status;
7516   PetscContainer     container;
7517   EnvelopeData      *edata;
7518   Vec                seq, par;
7519   IS                 isglobal;
7520 
7521   PetscFunctionBegin;
7522   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7523   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7524   if (!set || !flag) {
7525     /* TODO: only needs nonzero structure of transpose */
7526     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7527     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7528   }
7529   PetscCall(MatAIJGetLocalMat(AA, &A));
7530   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7531   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7532 
7533   PetscCall(MatGetLocalSize(mat, &n, NULL));
7534   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7535   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7536   PetscCallMPI(MPI_Comm_size(comm, &size));
7537   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7538 
7539   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7540 
7541   if (rank > 0) {
7542     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7543     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7544   }
7545   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7546   for (i = 0; i < n; i++) {
7547     env = PetscMax(env, ja[ia[i + 1] - 1]);
7548     II  = rstart + i;
7549     if (env == II) {
7550       starts[lblocks]  = tbs;
7551       sizes[lblocks++] = 1 + II - tbs;
7552       tbs              = 1 + II;
7553     }
7554   }
7555   if (rank < size - 1) {
7556     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7557     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7558   }
7559 
7560   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7561   if (!set || !flag) PetscCall(MatDestroy(&AA));
7562   PetscCall(MatDestroy(&A));
7563 
7564   PetscCall(PetscNew(&edata));
7565   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7566   edata->n = lblocks;
7567   /* create IS needed for extracting blocks from the original matrix */
7568   PetscCall(PetscMalloc1(lblocks, &edata->is));
7569   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7570 
7571   /* Create the resulting inverse matrix structure with preallocation information */
7572   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7573   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7574   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7575   PetscCall(MatSetType(edata->C, MATAIJ));
7576 
7577   /* Communicate the start and end of each row, from each block to the correct rank */
7578   /* TODO: Use PetscSF instead of VecScatter */
7579   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7580   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7581   PetscCall(VecGetArrayWrite(seq, &seqv));
7582   for (PetscInt i = 0; i < lblocks; i++) {
7583     for (PetscInt j = 0; j < sizes[i]; j++) {
7584       seqv[cnt]     = starts[i];
7585       seqv[cnt + 1] = starts[i] + sizes[i];
7586       cnt += 2;
7587     }
7588   }
7589   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7590   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7591   sc -= cnt;
7592   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7593   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7594   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7595   PetscCall(ISDestroy(&isglobal));
7596   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7597   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7598   PetscCall(VecScatterDestroy(&scatter));
7599   PetscCall(VecDestroy(&seq));
7600   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7601   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7602   PetscCall(VecGetArrayRead(par, &parv));
7603   cnt = 0;
7604   PetscCall(MatGetSize(mat, NULL, &n));
7605   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7606     PetscInt start, end, d = 0, od = 0;
7607 
7608     start = (PetscInt)PetscRealPart(parv[cnt]);
7609     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7610     cnt += 2;
7611 
7612     if (start < cstart) {
7613       od += cstart - start + n - cend;
7614       d += cend - cstart;
7615     } else if (start < cend) {
7616       od += n - cend;
7617       d += cend - start;
7618     } else od += n - start;
7619     if (end <= cstart) {
7620       od -= cstart - end + n - cend;
7621       d -= cend - cstart;
7622     } else if (end < cend) {
7623       od -= n - cend;
7624       d -= cend - end;
7625     } else od -= n - end;
7626 
7627     odiag[i] = od;
7628     diag[i]  = d;
7629   }
7630   PetscCall(VecRestoreArrayRead(par, &parv));
7631   PetscCall(VecDestroy(&par));
7632   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7633   PetscCall(PetscFree2(diag, odiag));
7634   PetscCall(PetscFree2(sizes, starts));
7635 
7636   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7637   PetscCall(PetscContainerSetPointer(container, edata));
7638   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7639   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7640   PetscCall(PetscObjectDereference((PetscObject)container));
7641   PetscFunctionReturn(PETSC_SUCCESS);
7642 }
7643 
7644 /*@
7645   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7646 
7647   Collective
7648 
7649   Input Parameters:
7650 + A     - the matrix
7651 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7652 
7653   Output Parameter:
7654 . C - matrix with inverted block diagonal of `A`
7655 
7656   Level: advanced
7657 
7658   Note:
7659   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7660 
7661 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7662 @*/
7663 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7664 {
7665   PetscContainer   container;
7666   EnvelopeData    *edata;
7667   PetscObjectState nonzerostate;
7668 
7669   PetscFunctionBegin;
7670   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7671   if (!container) {
7672     PetscCall(MatComputeVariableBlockEnvelope(A));
7673     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7674   }
7675   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7676   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7677   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7678   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7679 
7680   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7681   *C = edata->C;
7682 
7683   for (PetscInt i = 0; i < edata->n; i++) {
7684     Mat          D;
7685     PetscScalar *dvalues;
7686 
7687     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7688     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7689     PetscCall(MatSeqDenseInvert(D));
7690     PetscCall(MatDenseGetArray(D, &dvalues));
7691     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7692     PetscCall(MatDestroy(&D));
7693   }
7694   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7695   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7696   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7697   PetscFunctionReturn(PETSC_SUCCESS);
7698 }
7699 
7700 /*@
7701   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7702 
7703   Logically Collective
7704 
7705   Input Parameters:
7706 + mat     - the matrix
7707 . nblocks - the number of blocks on this process, each block can only exist on a single process
7708 - bsizes  - the block sizes
7709 
7710   Level: intermediate
7711 
7712   Notes:
7713   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7714 
7715   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.
7716 
7717 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7718           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7719 @*/
7720 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7721 {
7722   PetscInt i, ncnt = 0, nlocal;
7723 
7724   PetscFunctionBegin;
7725   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7726   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7727   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7728   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7729   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);
7730   PetscCall(PetscFree(mat->bsizes));
7731   mat->nblocks = nblocks;
7732   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7733   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7734   PetscFunctionReturn(PETSC_SUCCESS);
7735 }
7736 
7737 /*@C
7738   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7739 
7740   Logically Collective; No Fortran Support
7741 
7742   Input Parameter:
7743 . mat - the matrix
7744 
7745   Output Parameters:
7746 + nblocks - the number of blocks on this process
7747 - bsizes  - the block sizes
7748 
7749   Level: intermediate
7750 
7751 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7752 @*/
7753 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7754 {
7755   PetscFunctionBegin;
7756   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7757   *nblocks = mat->nblocks;
7758   *bsizes  = mat->bsizes;
7759   PetscFunctionReturn(PETSC_SUCCESS);
7760 }
7761 
7762 /*@
7763   MatSetBlockSizes - Sets the matrix block row and column sizes.
7764 
7765   Logically Collective
7766 
7767   Input Parameters:
7768 + mat - the matrix
7769 . rbs - row block size
7770 - cbs - column block size
7771 
7772   Level: intermediate
7773 
7774   Notes:
7775   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7776   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7777   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7778 
7779   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7780   are compatible with the matrix local sizes.
7781 
7782   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7783 
7784 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7785 @*/
7786 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7787 {
7788   PetscFunctionBegin;
7789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7790   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7791   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7792   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7793   if (mat->rmap->refcnt) {
7794     ISLocalToGlobalMapping l2g  = NULL;
7795     PetscLayout            nmap = NULL;
7796 
7797     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7798     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7799     PetscCall(PetscLayoutDestroy(&mat->rmap));
7800     mat->rmap          = nmap;
7801     mat->rmap->mapping = l2g;
7802   }
7803   if (mat->cmap->refcnt) {
7804     ISLocalToGlobalMapping l2g  = NULL;
7805     PetscLayout            nmap = NULL;
7806 
7807     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7808     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7809     PetscCall(PetscLayoutDestroy(&mat->cmap));
7810     mat->cmap          = nmap;
7811     mat->cmap->mapping = l2g;
7812   }
7813   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7814   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7815   PetscFunctionReturn(PETSC_SUCCESS);
7816 }
7817 
7818 /*@
7819   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7820 
7821   Logically Collective
7822 
7823   Input Parameters:
7824 + mat     - the matrix
7825 . fromRow - matrix from which to copy row block size
7826 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7827 
7828   Level: developer
7829 
7830 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7831 @*/
7832 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7833 {
7834   PetscFunctionBegin;
7835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7836   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7837   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7838   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7839   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7840   PetscFunctionReturn(PETSC_SUCCESS);
7841 }
7842 
7843 /*@
7844   MatResidual - Default routine to calculate the residual r = b - Ax
7845 
7846   Collective
7847 
7848   Input Parameters:
7849 + mat - the matrix
7850 . b   - the right-hand-side
7851 - x   - the approximate solution
7852 
7853   Output Parameter:
7854 . r - location to store the residual
7855 
7856   Level: developer
7857 
7858 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7859 @*/
7860 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7861 {
7862   PetscFunctionBegin;
7863   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7864   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7865   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7866   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7867   PetscValidType(mat, 1);
7868   MatCheckPreallocated(mat, 1);
7869   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7870   if (!mat->ops->residual) {
7871     PetscCall(MatMult(mat, x, r));
7872     PetscCall(VecAYPX(r, -1.0, b));
7873   } else {
7874     PetscUseTypeMethod(mat, residual, b, x, r);
7875   }
7876   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7877   PetscFunctionReturn(PETSC_SUCCESS);
7878 }
7879 
7880 /*MC
7881     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7882 
7883     Synopsis:
7884     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7885 
7886     Not Collective
7887 
7888     Input Parameters:
7889 +   A - the matrix
7890 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7891 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7892 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7893                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7894                  always used.
7895 
7896     Output Parameters:
7897 +   n - number of local rows in the (possibly compressed) matrix
7898 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7899 .   ja - the column indices
7900 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7901            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7902 
7903     Level: developer
7904 
7905     Note:
7906     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7907 
7908 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7909 M*/
7910 
7911 /*MC
7912     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7913 
7914     Synopsis:
7915     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7916 
7917     Not Collective
7918 
7919     Input Parameters:
7920 +   A - the  matrix
7921 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7922 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7923     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7924                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7925                  always used.
7926 .   n - number of local rows in the (possibly compressed) matrix
7927 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7928 .   ja - the column indices
7929 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7930            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7931 
7932     Level: developer
7933 
7934 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7935 M*/
7936 
7937 /*@C
7938   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7939 
7940   Collective
7941 
7942   Input Parameters:
7943 + mat             - the matrix
7944 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7945 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7946 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7947                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7948                  always used.
7949 
7950   Output Parameters:
7951 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7952 . 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
7953 . ja   - the column indices, use `NULL` if not needed
7954 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7955            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7956 
7957   Level: developer
7958 
7959   Notes:
7960   You CANNOT change any of the ia[] or ja[] values.
7961 
7962   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7963 
7964   Fortran Notes:
7965   Use
7966 .vb
7967     PetscInt, pointer :: ia(:),ja(:)
7968     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7969     ! Access the ith and jth entries via ia(i) and ja(j)
7970 .ve
7971 
7972   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7973 
7974 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7975 @*/
7976 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7977 {
7978   PetscFunctionBegin;
7979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7980   PetscValidType(mat, 1);
7981   if (n) PetscAssertPointer(n, 5);
7982   if (ia) PetscAssertPointer(ia, 6);
7983   if (ja) PetscAssertPointer(ja, 7);
7984   if (done) PetscAssertPointer(done, 8);
7985   MatCheckPreallocated(mat, 1);
7986   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7987   else {
7988     if (done) *done = PETSC_TRUE;
7989     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7990     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7991     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7992   }
7993   PetscFunctionReturn(PETSC_SUCCESS);
7994 }
7995 
7996 /*@C
7997   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7998 
7999   Collective
8000 
8001   Input Parameters:
8002 + mat             - the matrix
8003 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8004 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8005                 symmetrized
8006 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8007                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8008                  always used.
8009 . n               - number of columns in the (possibly compressed) matrix
8010 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8011 - ja              - the row indices
8012 
8013   Output Parameter:
8014 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8015 
8016   Level: developer
8017 
8018 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8019 @*/
8020 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8021 {
8022   PetscFunctionBegin;
8023   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8024   PetscValidType(mat, 1);
8025   PetscAssertPointer(n, 5);
8026   if (ia) PetscAssertPointer(ia, 6);
8027   if (ja) PetscAssertPointer(ja, 7);
8028   PetscAssertPointer(done, 8);
8029   MatCheckPreallocated(mat, 1);
8030   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8031   else {
8032     *done = PETSC_TRUE;
8033     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8034   }
8035   PetscFunctionReturn(PETSC_SUCCESS);
8036 }
8037 
8038 /*@C
8039   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8040 
8041   Collective
8042 
8043   Input Parameters:
8044 + mat             - the matrix
8045 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8046 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8047 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8048                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8049                  always used.
8050 . n               - size of (possibly compressed) matrix
8051 . ia              - the row pointers
8052 - ja              - the column indices
8053 
8054   Output Parameter:
8055 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8056 
8057   Level: developer
8058 
8059   Note:
8060   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8061   us of the array after it has been restored. If you pass `NULL`, it will
8062   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8063 
8064   Fortran Note:
8065   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8066 
8067 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8068 @*/
8069 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8070 {
8071   PetscFunctionBegin;
8072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8073   PetscValidType(mat, 1);
8074   if (ia) PetscAssertPointer(ia, 6);
8075   if (ja) PetscAssertPointer(ja, 7);
8076   if (done) PetscAssertPointer(done, 8);
8077   MatCheckPreallocated(mat, 1);
8078 
8079   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8080   else {
8081     if (done) *done = PETSC_TRUE;
8082     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8083     if (n) *n = 0;
8084     if (ia) *ia = NULL;
8085     if (ja) *ja = NULL;
8086   }
8087   PetscFunctionReturn(PETSC_SUCCESS);
8088 }
8089 
8090 /*@C
8091   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8092 
8093   Collective
8094 
8095   Input Parameters:
8096 + mat             - the matrix
8097 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8098 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8099 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8100                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8101                  always used.
8102 
8103   Output Parameters:
8104 + n    - size of (possibly compressed) matrix
8105 . ia   - the column pointers
8106 . ja   - the row indices
8107 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8108 
8109   Level: developer
8110 
8111 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8112 @*/
8113 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8114 {
8115   PetscFunctionBegin;
8116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8117   PetscValidType(mat, 1);
8118   if (ia) PetscAssertPointer(ia, 6);
8119   if (ja) PetscAssertPointer(ja, 7);
8120   PetscAssertPointer(done, 8);
8121   MatCheckPreallocated(mat, 1);
8122 
8123   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8124   else {
8125     *done = PETSC_TRUE;
8126     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8127     if (n) *n = 0;
8128     if (ia) *ia = NULL;
8129     if (ja) *ja = NULL;
8130   }
8131   PetscFunctionReturn(PETSC_SUCCESS);
8132 }
8133 
8134 /*@C
8135   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8136   `MatGetColumnIJ()`.
8137 
8138   Collective
8139 
8140   Input Parameters:
8141 + mat        - the matrix
8142 . ncolors    - maximum color value
8143 . n          - number of entries in colorarray
8144 - colorarray - array indicating color for each column
8145 
8146   Output Parameter:
8147 . iscoloring - coloring generated using colorarray information
8148 
8149   Level: developer
8150 
8151 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8152 @*/
8153 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8154 {
8155   PetscFunctionBegin;
8156   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8157   PetscValidType(mat, 1);
8158   PetscAssertPointer(colorarray, 4);
8159   PetscAssertPointer(iscoloring, 5);
8160   MatCheckPreallocated(mat, 1);
8161 
8162   if (!mat->ops->coloringpatch) {
8163     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8164   } else {
8165     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8166   }
8167   PetscFunctionReturn(PETSC_SUCCESS);
8168 }
8169 
8170 /*@
8171   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8172 
8173   Logically Collective
8174 
8175   Input Parameter:
8176 . mat - the factored matrix to be reset
8177 
8178   Level: developer
8179 
8180   Notes:
8181   This routine should be used only with factored matrices formed by in-place
8182   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8183   format).  This option can save memory, for example, when solving nonlinear
8184   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8185   ILU(0) preconditioner.
8186 
8187   One can specify in-place ILU(0) factorization by calling
8188 .vb
8189      PCType(pc,PCILU);
8190      PCFactorSeUseInPlace(pc);
8191 .ve
8192   or by using the options -pc_type ilu -pc_factor_in_place
8193 
8194   In-place factorization ILU(0) can also be used as a local
8195   solver for the blocks within the block Jacobi or additive Schwarz
8196   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8197   for details on setting local solver options.
8198 
8199   Most users should employ the `KSP` interface for linear solvers
8200   instead of working directly with matrix algebra routines such as this.
8201   See, e.g., `KSPCreate()`.
8202 
8203 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8204 @*/
8205 PetscErrorCode MatSetUnfactored(Mat mat)
8206 {
8207   PetscFunctionBegin;
8208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8209   PetscValidType(mat, 1);
8210   MatCheckPreallocated(mat, 1);
8211   mat->factortype = MAT_FACTOR_NONE;
8212   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8213   PetscUseTypeMethod(mat, setunfactored);
8214   PetscFunctionReturn(PETSC_SUCCESS);
8215 }
8216 
8217 /*MC
8218     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8219 
8220     Synopsis:
8221     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8222 
8223     Not Collective
8224 
8225     Input Parameter:
8226 .   x - matrix
8227 
8228     Output Parameters:
8229 +   xx_v - the Fortran pointer to the array
8230 -   ierr - error code
8231 
8232     Example of Usage:
8233 .vb
8234       PetscScalar, pointer xx_v(:,:)
8235       ....
8236       call MatDenseGetArrayF90(x,xx_v,ierr)
8237       a = xx_v(3)
8238       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8239 .ve
8240 
8241     Level: advanced
8242 
8243 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8244 M*/
8245 
8246 /*MC
8247     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8248     accessed with `MatDenseGetArrayF90()`.
8249 
8250     Synopsis:
8251     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8252 
8253     Not Collective
8254 
8255     Input Parameters:
8256 +   x - matrix
8257 -   xx_v - the Fortran90 pointer to the array
8258 
8259     Output Parameter:
8260 .   ierr - error code
8261 
8262     Example of Usage:
8263 .vb
8264        PetscScalar, pointer xx_v(:,:)
8265        ....
8266        call MatDenseGetArrayF90(x,xx_v,ierr)
8267        a = xx_v(3)
8268        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8269 .ve
8270 
8271     Level: advanced
8272 
8273 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8274 M*/
8275 
8276 /*MC
8277     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8278 
8279     Synopsis:
8280     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8281 
8282     Not Collective
8283 
8284     Input Parameter:
8285 .   x - matrix
8286 
8287     Output Parameters:
8288 +   xx_v - the Fortran pointer to the array
8289 -   ierr - error code
8290 
8291     Example of Usage:
8292 .vb
8293       PetscScalar, pointer xx_v(:)
8294       ....
8295       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8296       a = xx_v(3)
8297       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8298 .ve
8299 
8300     Level: advanced
8301 
8302 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8303 M*/
8304 
8305 /*MC
8306     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8307     accessed with `MatSeqAIJGetArrayF90()`.
8308 
8309     Synopsis:
8310     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8311 
8312     Not Collective
8313 
8314     Input Parameters:
8315 +   x - matrix
8316 -   xx_v - the Fortran90 pointer to the array
8317 
8318     Output Parameter:
8319 .   ierr - error code
8320 
8321     Example of Usage:
8322 .vb
8323        PetscScalar, pointer xx_v(:)
8324        ....
8325        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8326        a = xx_v(3)
8327        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8328 .ve
8329 
8330     Level: advanced
8331 
8332 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8333 M*/
8334 
8335 /*@
8336   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8337   as the original matrix.
8338 
8339   Collective
8340 
8341   Input Parameters:
8342 + mat   - the original matrix
8343 . isrow - parallel `IS` containing the rows this processor should obtain
8344 . 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.
8345 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8346 
8347   Output Parameter:
8348 . newmat - the new submatrix, of the same type as the original matrix
8349 
8350   Level: advanced
8351 
8352   Notes:
8353   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8354 
8355   Some matrix types place restrictions on the row and column indices, such
8356   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;
8357   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8358 
8359   The index sets may not have duplicate entries.
8360 
8361   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8362   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8363   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8364   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8365   you are finished using it.
8366 
8367   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8368   the input matrix.
8369 
8370   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8371 
8372   If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature
8373   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8374 
8375   Example usage:
8376   Consider the following 8x8 matrix with 34 non-zero values, that is
8377   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8378   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8379   as follows
8380 .vb
8381             1  2  0  |  0  3  0  |  0  4
8382     Proc0   0  5  6  |  7  0  0  |  8  0
8383             9  0 10  | 11  0  0  | 12  0
8384     -------------------------------------
8385            13  0 14  | 15 16 17  |  0  0
8386     Proc1   0 18  0  | 19 20 21  |  0  0
8387             0  0  0  | 22 23  0  | 24  0
8388     -------------------------------------
8389     Proc2  25 26 27  |  0  0 28  | 29  0
8390            30  0  0  | 31 32 33  |  0 34
8391 .ve
8392 
8393   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8394 
8395 .vb
8396             2  0  |  0  3  0  |  0
8397     Proc0   5  6  |  7  0  0  |  8
8398     -------------------------------
8399     Proc1  18  0  | 19 20 21  |  0
8400     -------------------------------
8401     Proc2  26 27  |  0  0 28  | 29
8402             0  0  | 31 32 33  |  0
8403 .ve
8404 
8405 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8406 @*/
8407 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8408 {
8409   PetscMPIInt size;
8410   Mat        *local;
8411   IS          iscoltmp;
8412   PetscBool   flg;
8413 
8414   PetscFunctionBegin;
8415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8416   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8417   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8418   PetscAssertPointer(newmat, 5);
8419   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8420   PetscValidType(mat, 1);
8421   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8422   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8423 
8424   MatCheckPreallocated(mat, 1);
8425   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8426 
8427   if (!iscol || isrow == iscol) {
8428     PetscBool   stride;
8429     PetscMPIInt grabentirematrix = 0, grab;
8430     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8431     if (stride) {
8432       PetscInt first, step, n, rstart, rend;
8433       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8434       if (step == 1) {
8435         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8436         if (rstart == first) {
8437           PetscCall(ISGetLocalSize(isrow, &n));
8438           if (n == rend - rstart) grabentirematrix = 1;
8439         }
8440       }
8441     }
8442     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8443     if (grab) {
8444       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8445       if (cll == MAT_INITIAL_MATRIX) {
8446         *newmat = mat;
8447         PetscCall(PetscObjectReference((PetscObject)mat));
8448       }
8449       PetscFunctionReturn(PETSC_SUCCESS);
8450     }
8451   }
8452 
8453   if (!iscol) {
8454     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8455   } else {
8456     iscoltmp = iscol;
8457   }
8458 
8459   /* if original matrix is on just one processor then use submatrix generated */
8460   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8461     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8462     goto setproperties;
8463   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8464     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8465     *newmat = *local;
8466     PetscCall(PetscFree(local));
8467     goto setproperties;
8468   } else if (!mat->ops->createsubmatrix) {
8469     /* Create a new matrix type that implements the operation using the full matrix */
8470     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8471     switch (cll) {
8472     case MAT_INITIAL_MATRIX:
8473       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8474       break;
8475     case MAT_REUSE_MATRIX:
8476       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8477       break;
8478     default:
8479       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8480     }
8481     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8482     goto setproperties;
8483   }
8484 
8485   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8486   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8487   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8488 
8489 setproperties:
8490   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8491   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8492   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8493   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8494   PetscFunctionReturn(PETSC_SUCCESS);
8495 }
8496 
8497 /*@
8498   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8499 
8500   Not Collective
8501 
8502   Input Parameters:
8503 + A - the matrix we wish to propagate options from
8504 - B - the matrix we wish to propagate options to
8505 
8506   Level: beginner
8507 
8508   Note:
8509   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8510 
8511 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8512 @*/
8513 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8514 {
8515   PetscFunctionBegin;
8516   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8517   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8518   B->symmetry_eternal            = A->symmetry_eternal;
8519   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8520   B->symmetric                   = A->symmetric;
8521   B->structurally_symmetric      = A->structurally_symmetric;
8522   B->spd                         = A->spd;
8523   B->hermitian                   = A->hermitian;
8524   PetscFunctionReturn(PETSC_SUCCESS);
8525 }
8526 
8527 /*@
8528   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8529   used during the assembly process to store values that belong to
8530   other processors.
8531 
8532   Not Collective
8533 
8534   Input Parameters:
8535 + mat   - the matrix
8536 . size  - the initial size of the stash.
8537 - bsize - the initial size of the block-stash(if used).
8538 
8539   Options Database Keys:
8540 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8541 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8542 
8543   Level: intermediate
8544 
8545   Notes:
8546   The block-stash is used for values set with `MatSetValuesBlocked()` while
8547   the stash is used for values set with `MatSetValues()`
8548 
8549   Run with the option -info and look for output of the form
8550   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8551   to determine the appropriate value, MM, to use for size and
8552   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8553   to determine the value, BMM to use for bsize
8554 
8555 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8556 @*/
8557 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8558 {
8559   PetscFunctionBegin;
8560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8561   PetscValidType(mat, 1);
8562   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8563   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8564   PetscFunctionReturn(PETSC_SUCCESS);
8565 }
8566 
8567 /*@
8568   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8569   the matrix
8570 
8571   Neighbor-wise Collective
8572 
8573   Input Parameters:
8574 + A - the matrix
8575 . x - the vector to be multiplied by the interpolation operator
8576 - y - the vector to be added to the result
8577 
8578   Output Parameter:
8579 . w - the resulting vector
8580 
8581   Level: intermediate
8582 
8583   Notes:
8584   `w` may be the same vector as `y`.
8585 
8586   This allows one to use either the restriction or interpolation (its transpose)
8587   matrix to do the interpolation
8588 
8589 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8590 @*/
8591 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8592 {
8593   PetscInt M, N, Ny;
8594 
8595   PetscFunctionBegin;
8596   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8597   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8598   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8599   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8600   PetscCall(MatGetSize(A, &M, &N));
8601   PetscCall(VecGetSize(y, &Ny));
8602   if (M == Ny) {
8603     PetscCall(MatMultAdd(A, x, y, w));
8604   } else {
8605     PetscCall(MatMultTransposeAdd(A, x, y, w));
8606   }
8607   PetscFunctionReturn(PETSC_SUCCESS);
8608 }
8609 
8610 /*@
8611   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8612   the matrix
8613 
8614   Neighbor-wise Collective
8615 
8616   Input Parameters:
8617 + A - the matrix
8618 - x - the vector to be interpolated
8619 
8620   Output Parameter:
8621 . y - the resulting vector
8622 
8623   Level: intermediate
8624 
8625   Note:
8626   This allows one to use either the restriction or interpolation (its transpose)
8627   matrix to do the interpolation
8628 
8629 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8630 @*/
8631 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8632 {
8633   PetscInt M, N, Ny;
8634 
8635   PetscFunctionBegin;
8636   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8637   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8638   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8639   PetscCall(MatGetSize(A, &M, &N));
8640   PetscCall(VecGetSize(y, &Ny));
8641   if (M == Ny) {
8642     PetscCall(MatMult(A, x, y));
8643   } else {
8644     PetscCall(MatMultTranspose(A, x, y));
8645   }
8646   PetscFunctionReturn(PETSC_SUCCESS);
8647 }
8648 
8649 /*@
8650   MatRestrict - $y = A*x$ or $A^T*x$
8651 
8652   Neighbor-wise Collective
8653 
8654   Input Parameters:
8655 + A - the matrix
8656 - x - the vector to be restricted
8657 
8658   Output Parameter:
8659 . y - the resulting vector
8660 
8661   Level: intermediate
8662 
8663   Note:
8664   This allows one to use either the restriction or interpolation (its transpose)
8665   matrix to do the restriction
8666 
8667 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8668 @*/
8669 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8670 {
8671   PetscInt M, N, Ny;
8672 
8673   PetscFunctionBegin;
8674   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8675   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8676   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8677   PetscCall(MatGetSize(A, &M, &N));
8678   PetscCall(VecGetSize(y, &Ny));
8679   if (M == Ny) {
8680     PetscCall(MatMult(A, x, y));
8681   } else {
8682     PetscCall(MatMultTranspose(A, x, y));
8683   }
8684   PetscFunctionReturn(PETSC_SUCCESS);
8685 }
8686 
8687 /*@
8688   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8689 
8690   Neighbor-wise Collective
8691 
8692   Input Parameters:
8693 + A - the matrix
8694 . x - the input dense matrix to be multiplied
8695 - w - the input dense matrix to be added to the result
8696 
8697   Output Parameter:
8698 . y - the output dense matrix
8699 
8700   Level: intermediate
8701 
8702   Note:
8703   This allows one to use either the restriction or interpolation (its transpose)
8704   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8705   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8706 
8707 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8708 @*/
8709 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8710 {
8711   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8712   PetscBool trans = PETSC_TRUE;
8713   MatReuse  reuse = MAT_INITIAL_MATRIX;
8714 
8715   PetscFunctionBegin;
8716   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8717   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8718   PetscValidType(x, 2);
8719   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8720   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8721   PetscCall(MatGetSize(A, &M, &N));
8722   PetscCall(MatGetSize(x, &Mx, &Nx));
8723   if (N == Mx) trans = PETSC_FALSE;
8724   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);
8725   Mo = trans ? N : M;
8726   if (*y) {
8727     PetscCall(MatGetSize(*y, &My, &Ny));
8728     if (Mo == My && Nx == Ny) {
8729       reuse = MAT_REUSE_MATRIX;
8730     } else {
8731       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);
8732       PetscCall(MatDestroy(y));
8733     }
8734   }
8735 
8736   if (w && *y == w) { /* this is to minimize changes in PCMG */
8737     PetscBool flg;
8738 
8739     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8740     if (w) {
8741       PetscInt My, Ny, Mw, Nw;
8742 
8743       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8744       PetscCall(MatGetSize(*y, &My, &Ny));
8745       PetscCall(MatGetSize(w, &Mw, &Nw));
8746       if (!flg || My != Mw || Ny != Nw) w = NULL;
8747     }
8748     if (!w) {
8749       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8750       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8751       PetscCall(PetscObjectDereference((PetscObject)w));
8752     } else {
8753       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8754     }
8755   }
8756   if (!trans) {
8757     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8758   } else {
8759     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8760   }
8761   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8762   PetscFunctionReturn(PETSC_SUCCESS);
8763 }
8764 
8765 /*@
8766   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8767 
8768   Neighbor-wise Collective
8769 
8770   Input Parameters:
8771 + A - the matrix
8772 - x - the input dense matrix
8773 
8774   Output Parameter:
8775 . y - the output dense matrix
8776 
8777   Level: intermediate
8778 
8779   Note:
8780   This allows one to use either the restriction or interpolation (its transpose)
8781   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8782   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8783 
8784 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8785 @*/
8786 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8787 {
8788   PetscFunctionBegin;
8789   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8790   PetscFunctionReturn(PETSC_SUCCESS);
8791 }
8792 
8793 /*@
8794   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8795 
8796   Neighbor-wise Collective
8797 
8798   Input Parameters:
8799 + A - the matrix
8800 - x - the input dense matrix
8801 
8802   Output Parameter:
8803 . y - the output dense matrix
8804 
8805   Level: intermediate
8806 
8807   Note:
8808   This allows one to use either the restriction or interpolation (its transpose)
8809   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8810   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8811 
8812 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8813 @*/
8814 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8815 {
8816   PetscFunctionBegin;
8817   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8818   PetscFunctionReturn(PETSC_SUCCESS);
8819 }
8820 
8821 /*@
8822   MatGetNullSpace - retrieves the null space of a matrix.
8823 
8824   Logically Collective
8825 
8826   Input Parameters:
8827 + mat    - the matrix
8828 - nullsp - the null space object
8829 
8830   Level: developer
8831 
8832 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8833 @*/
8834 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8835 {
8836   PetscFunctionBegin;
8837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8838   PetscAssertPointer(nullsp, 2);
8839   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8840   PetscFunctionReturn(PETSC_SUCCESS);
8841 }
8842 
8843 /*@
8844   MatSetNullSpace - attaches a null space to a matrix.
8845 
8846   Logically Collective
8847 
8848   Input Parameters:
8849 + mat    - the matrix
8850 - nullsp - the null space object
8851 
8852   Level: advanced
8853 
8854   Notes:
8855   This null space is used by the `KSP` linear solvers to solve singular systems.
8856 
8857   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`
8858 
8859   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
8860   to zero but the linear system will still be solved in a least squares sense.
8861 
8862   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8863   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)$.
8864   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
8865   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
8866   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$).
8867   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8868 
8869   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8870   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8871   routine also automatically calls `MatSetTransposeNullSpace()`.
8872 
8873   The user should call `MatNullSpaceDestroy()`.
8874 
8875 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8876           `KSPSetPCSide()`
8877 @*/
8878 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8879 {
8880   PetscFunctionBegin;
8881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8882   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8883   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8884   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8885   mat->nullsp = nullsp;
8886   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8887   PetscFunctionReturn(PETSC_SUCCESS);
8888 }
8889 
8890 /*@
8891   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8892 
8893   Logically Collective
8894 
8895   Input Parameters:
8896 + mat    - the matrix
8897 - nullsp - the null space object
8898 
8899   Level: developer
8900 
8901 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8902 @*/
8903 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8904 {
8905   PetscFunctionBegin;
8906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8907   PetscValidType(mat, 1);
8908   PetscAssertPointer(nullsp, 2);
8909   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8910   PetscFunctionReturn(PETSC_SUCCESS);
8911 }
8912 
8913 /*@
8914   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8915 
8916   Logically Collective
8917 
8918   Input Parameters:
8919 + mat    - the matrix
8920 - nullsp - the null space object
8921 
8922   Level: advanced
8923 
8924   Notes:
8925   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8926 
8927   See `MatSetNullSpace()`
8928 
8929 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8930 @*/
8931 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8932 {
8933   PetscFunctionBegin;
8934   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8935   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8936   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8937   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8938   mat->transnullsp = nullsp;
8939   PetscFunctionReturn(PETSC_SUCCESS);
8940 }
8941 
8942 /*@
8943   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8944   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8945 
8946   Logically Collective
8947 
8948   Input Parameters:
8949 + mat    - the matrix
8950 - nullsp - the null space object
8951 
8952   Level: advanced
8953 
8954   Notes:
8955   Overwrites any previous near null space that may have been attached
8956 
8957   You can remove the null space by calling this routine with an `nullsp` of `NULL`
8958 
8959 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8960 @*/
8961 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8962 {
8963   PetscFunctionBegin;
8964   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8965   PetscValidType(mat, 1);
8966   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8967   MatCheckPreallocated(mat, 1);
8968   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8969   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8970   mat->nearnullsp = nullsp;
8971   PetscFunctionReturn(PETSC_SUCCESS);
8972 }
8973 
8974 /*@
8975   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8976 
8977   Not Collective
8978 
8979   Input Parameter:
8980 . mat - the matrix
8981 
8982   Output Parameter:
8983 . nullsp - the null space object, `NULL` if not set
8984 
8985   Level: advanced
8986 
8987 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8988 @*/
8989 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8990 {
8991   PetscFunctionBegin;
8992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8993   PetscValidType(mat, 1);
8994   PetscAssertPointer(nullsp, 2);
8995   MatCheckPreallocated(mat, 1);
8996   *nullsp = mat->nearnullsp;
8997   PetscFunctionReturn(PETSC_SUCCESS);
8998 }
8999 
9000 /*@C
9001   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9002 
9003   Collective
9004 
9005   Input Parameters:
9006 + mat  - the matrix
9007 . row  - row/column permutation
9008 - info - information on desired factorization process
9009 
9010   Level: developer
9011 
9012   Notes:
9013   Probably really in-place only when level of fill is zero, otherwise allocates
9014   new space to store factored matrix and deletes previous memory.
9015 
9016   Most users should employ the `KSP` interface for linear solvers
9017   instead of working directly with matrix algebra routines such as this.
9018   See, e.g., `KSPCreate()`.
9019 
9020   Developer Note:
9021   The Fortran interface is not autogenerated as the
9022   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9023 
9024 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9025 @*/
9026 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9027 {
9028   PetscFunctionBegin;
9029   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9030   PetscValidType(mat, 1);
9031   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9032   PetscAssertPointer(info, 3);
9033   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9034   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9035   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9036   MatCheckPreallocated(mat, 1);
9037   PetscUseTypeMethod(mat, iccfactor, row, info);
9038   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9039   PetscFunctionReturn(PETSC_SUCCESS);
9040 }
9041 
9042 /*@
9043   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9044   ghosted ones.
9045 
9046   Not Collective
9047 
9048   Input Parameters:
9049 + mat  - the matrix
9050 - diag - the diagonal values, including ghost ones
9051 
9052   Level: developer
9053 
9054   Notes:
9055   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9056 
9057   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9058 
9059 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9060 @*/
9061 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9062 {
9063   PetscMPIInt size;
9064 
9065   PetscFunctionBegin;
9066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9067   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9068   PetscValidType(mat, 1);
9069 
9070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9071   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9072   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9073   if (size == 1) {
9074     PetscInt n, m;
9075     PetscCall(VecGetSize(diag, &n));
9076     PetscCall(MatGetSize(mat, NULL, &m));
9077     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9078     PetscCall(MatDiagonalScale(mat, NULL, diag));
9079   } else {
9080     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9081   }
9082   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9083   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9084   PetscFunctionReturn(PETSC_SUCCESS);
9085 }
9086 
9087 /*@
9088   MatGetInertia - Gets the inertia from a factored matrix
9089 
9090   Collective
9091 
9092   Input Parameter:
9093 . mat - the matrix
9094 
9095   Output Parameters:
9096 + nneg  - number of negative eigenvalues
9097 . nzero - number of zero eigenvalues
9098 - npos  - number of positive eigenvalues
9099 
9100   Level: advanced
9101 
9102   Note:
9103   Matrix must have been factored by `MatCholeskyFactor()`
9104 
9105 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9106 @*/
9107 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9108 {
9109   PetscFunctionBegin;
9110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9111   PetscValidType(mat, 1);
9112   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9113   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9114   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9115   PetscFunctionReturn(PETSC_SUCCESS);
9116 }
9117 
9118 /*@C
9119   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9120 
9121   Neighbor-wise Collective
9122 
9123   Input Parameters:
9124 + mat - the factored matrix obtained with `MatGetFactor()`
9125 - b   - the right-hand-side vectors
9126 
9127   Output Parameter:
9128 . x - the result vectors
9129 
9130   Level: developer
9131 
9132   Note:
9133   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9134   call `MatSolves`(A,x,x).
9135 
9136 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9137 @*/
9138 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9139 {
9140   PetscFunctionBegin;
9141   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9142   PetscValidType(mat, 1);
9143   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9144   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9145   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9146 
9147   MatCheckPreallocated(mat, 1);
9148   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9149   PetscUseTypeMethod(mat, solves, b, x);
9150   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9151   PetscFunctionReturn(PETSC_SUCCESS);
9152 }
9153 
9154 /*@
9155   MatIsSymmetric - Test whether a matrix is symmetric
9156 
9157   Collective
9158 
9159   Input Parameters:
9160 + A   - the matrix to test
9161 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9162 
9163   Output Parameter:
9164 . flg - the result
9165 
9166   Level: intermediate
9167 
9168   Notes:
9169   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9170 
9171   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9172 
9173   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9174   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9175 
9176 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9177           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9178 @*/
9179 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9180 {
9181   PetscFunctionBegin;
9182   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9183   PetscAssertPointer(flg, 3);
9184 
9185   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9186   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9187   else {
9188     PetscUseTypeMethod(A, issymmetric, tol, flg);
9189     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9190   }
9191   PetscFunctionReturn(PETSC_SUCCESS);
9192 }
9193 
9194 /*@
9195   MatIsHermitian - Test whether a matrix is Hermitian
9196 
9197   Collective
9198 
9199   Input Parameters:
9200 + A   - the matrix to test
9201 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9202 
9203   Output Parameter:
9204 . flg - the result
9205 
9206   Level: intermediate
9207 
9208   Notes:
9209   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9210 
9211   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9212 
9213   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9214   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9215 
9216 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9217           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9218 @*/
9219 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9220 {
9221   PetscFunctionBegin;
9222   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9223   PetscAssertPointer(flg, 3);
9224 
9225   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9226   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9227   else {
9228     PetscUseTypeMethod(A, ishermitian, tol, flg);
9229     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9230   }
9231   PetscFunctionReturn(PETSC_SUCCESS);
9232 }
9233 
9234 /*@
9235   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9236 
9237   Not Collective
9238 
9239   Input Parameter:
9240 . A - the matrix to check
9241 
9242   Output Parameters:
9243 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9244 - flg - the result (only valid if set is `PETSC_TRUE`)
9245 
9246   Level: advanced
9247 
9248   Notes:
9249   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9250   if you want it explicitly checked
9251 
9252   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9253   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9254 
9255 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9256 @*/
9257 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9258 {
9259   PetscFunctionBegin;
9260   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9261   PetscAssertPointer(set, 2);
9262   PetscAssertPointer(flg, 3);
9263   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9264     *set = PETSC_TRUE;
9265     *flg = PetscBool3ToBool(A->symmetric);
9266   } else {
9267     *set = PETSC_FALSE;
9268   }
9269   PetscFunctionReturn(PETSC_SUCCESS);
9270 }
9271 
9272 /*@
9273   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9274 
9275   Not Collective
9276 
9277   Input Parameter:
9278 . A - the matrix to check
9279 
9280   Output Parameters:
9281 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9282 - flg - the result (only valid if set is `PETSC_TRUE`)
9283 
9284   Level: advanced
9285 
9286   Notes:
9287   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9288 
9289   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9290   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9291 
9292 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9293 @*/
9294 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9295 {
9296   PetscFunctionBegin;
9297   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9298   PetscAssertPointer(set, 2);
9299   PetscAssertPointer(flg, 3);
9300   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9301     *set = PETSC_TRUE;
9302     *flg = PetscBool3ToBool(A->spd);
9303   } else {
9304     *set = PETSC_FALSE;
9305   }
9306   PetscFunctionReturn(PETSC_SUCCESS);
9307 }
9308 
9309 /*@
9310   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9311 
9312   Not Collective
9313 
9314   Input Parameter:
9315 . A - the matrix to check
9316 
9317   Output Parameters:
9318 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9319 - flg - the result (only valid if set is `PETSC_TRUE`)
9320 
9321   Level: advanced
9322 
9323   Notes:
9324   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9325   if you want it explicitly checked
9326 
9327   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9328   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9329 
9330 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9331 @*/
9332 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9333 {
9334   PetscFunctionBegin;
9335   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9336   PetscAssertPointer(set, 2);
9337   PetscAssertPointer(flg, 3);
9338   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9339     *set = PETSC_TRUE;
9340     *flg = PetscBool3ToBool(A->hermitian);
9341   } else {
9342     *set = PETSC_FALSE;
9343   }
9344   PetscFunctionReturn(PETSC_SUCCESS);
9345 }
9346 
9347 /*@
9348   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9349 
9350   Collective
9351 
9352   Input Parameter:
9353 . A - the matrix to test
9354 
9355   Output Parameter:
9356 . flg - the result
9357 
9358   Level: intermediate
9359 
9360   Notes:
9361   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9362 
9363   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
9364   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9365 
9366 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9367 @*/
9368 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9369 {
9370   PetscFunctionBegin;
9371   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9372   PetscAssertPointer(flg, 2);
9373   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9374     *flg = PetscBool3ToBool(A->structurally_symmetric);
9375   } else {
9376     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9377     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9378   }
9379   PetscFunctionReturn(PETSC_SUCCESS);
9380 }
9381 
9382 /*@
9383   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9384 
9385   Not Collective
9386 
9387   Input Parameter:
9388 . A - the matrix to check
9389 
9390   Output Parameters:
9391 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9392 - flg - the result (only valid if set is PETSC_TRUE)
9393 
9394   Level: advanced
9395 
9396   Notes:
9397   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
9398   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9399 
9400   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9401 
9402 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9403 @*/
9404 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9405 {
9406   PetscFunctionBegin;
9407   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9408   PetscAssertPointer(set, 2);
9409   PetscAssertPointer(flg, 3);
9410   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9411     *set = PETSC_TRUE;
9412     *flg = PetscBool3ToBool(A->structurally_symmetric);
9413   } else {
9414     *set = PETSC_FALSE;
9415   }
9416   PetscFunctionReturn(PETSC_SUCCESS);
9417 }
9418 
9419 /*@
9420   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9421   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9422 
9423   Not Collective
9424 
9425   Input Parameter:
9426 . mat - the matrix
9427 
9428   Output Parameters:
9429 + nstash    - the size of the stash
9430 . reallocs  - the number of additional mallocs incurred.
9431 . bnstash   - the size of the block stash
9432 - breallocs - the number of additional mallocs incurred.in the block stash
9433 
9434   Level: advanced
9435 
9436 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9437 @*/
9438 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9439 {
9440   PetscFunctionBegin;
9441   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9442   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9443   PetscFunctionReturn(PETSC_SUCCESS);
9444 }
9445 
9446 /*@C
9447   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9448   parallel layout, `PetscLayout` for rows and columns
9449 
9450   Collective
9451 
9452   Input Parameter:
9453 . mat - the matrix
9454 
9455   Output Parameters:
9456 + right - (optional) vector that the matrix can be multiplied against
9457 - left  - (optional) vector that the matrix vector product can be stored in
9458 
9459   Level: advanced
9460 
9461   Notes:
9462   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()`.
9463 
9464   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9465 
9466 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9467 @*/
9468 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9469 {
9470   PetscFunctionBegin;
9471   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9472   PetscValidType(mat, 1);
9473   if (mat->ops->getvecs) {
9474     PetscUseTypeMethod(mat, getvecs, right, left);
9475   } else {
9476     if (right) {
9477       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9478       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9479       PetscCall(VecSetType(*right, mat->defaultvectype));
9480 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9481       if (mat->boundtocpu && mat->bindingpropagates) {
9482         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9483         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9484       }
9485 #endif
9486     }
9487     if (left) {
9488       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9489       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9490       PetscCall(VecSetType(*left, mat->defaultvectype));
9491 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9492       if (mat->boundtocpu && mat->bindingpropagates) {
9493         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9494         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9495       }
9496 #endif
9497     }
9498   }
9499   PetscFunctionReturn(PETSC_SUCCESS);
9500 }
9501 
9502 /*@C
9503   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9504   with default values.
9505 
9506   Not Collective
9507 
9508   Input Parameter:
9509 . info - the `MatFactorInfo` data structure
9510 
9511   Level: developer
9512 
9513   Notes:
9514   The solvers are generally used through the `KSP` and `PC` objects, for example
9515   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9516 
9517   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9518 
9519   Developer Note:
9520   The Fortran interface is not autogenerated as the
9521   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9522 
9523 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9524 @*/
9525 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9526 {
9527   PetscFunctionBegin;
9528   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9529   PetscFunctionReturn(PETSC_SUCCESS);
9530 }
9531 
9532 /*@
9533   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9534 
9535   Collective
9536 
9537   Input Parameters:
9538 + mat - the factored matrix
9539 - is  - the index set defining the Schur indices (0-based)
9540 
9541   Level: advanced
9542 
9543   Notes:
9544   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9545 
9546   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9547 
9548   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9549 
9550 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9551           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9552 @*/
9553 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9554 {
9555   PetscErrorCode (*f)(Mat, IS);
9556 
9557   PetscFunctionBegin;
9558   PetscValidType(mat, 1);
9559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9560   PetscValidType(is, 2);
9561   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9562   PetscCheckSameComm(mat, 1, is, 2);
9563   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9564   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9565   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9566   PetscCall(MatDestroy(&mat->schur));
9567   PetscCall((*f)(mat, is));
9568   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9569   PetscFunctionReturn(PETSC_SUCCESS);
9570 }
9571 
9572 /*@
9573   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9574 
9575   Logically Collective
9576 
9577   Input Parameters:
9578 + F      - the factored matrix obtained by calling `MatGetFactor()`
9579 . S      - location where to return the Schur complement, can be `NULL`
9580 - status - the status of the Schur complement matrix, can be `NULL`
9581 
9582   Level: advanced
9583 
9584   Notes:
9585   You must call `MatFactorSetSchurIS()` before calling this routine.
9586 
9587   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9588 
9589   The routine provides a copy of the Schur matrix stored within the solver data structures.
9590   The caller must destroy the object when it is no longer needed.
9591   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9592 
9593   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)
9594 
9595   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9596 
9597   Developer Note:
9598   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9599   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9600 
9601 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9602 @*/
9603 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9604 {
9605   PetscFunctionBegin;
9606   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9607   if (S) PetscAssertPointer(S, 2);
9608   if (status) PetscAssertPointer(status, 3);
9609   if (S) {
9610     PetscErrorCode (*f)(Mat, Mat *);
9611 
9612     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9613     if (f) {
9614       PetscCall((*f)(F, S));
9615     } else {
9616       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9617     }
9618   }
9619   if (status) *status = F->schur_status;
9620   PetscFunctionReturn(PETSC_SUCCESS);
9621 }
9622 
9623 /*@
9624   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9625 
9626   Logically Collective
9627 
9628   Input Parameters:
9629 + F      - the factored matrix obtained by calling `MatGetFactor()`
9630 . S      - location where to return the Schur complement, can be `NULL`
9631 - status - the status of the Schur complement matrix, can be `NULL`
9632 
9633   Level: advanced
9634 
9635   Notes:
9636   You must call `MatFactorSetSchurIS()` before calling this routine.
9637 
9638   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9639 
9640   The routine returns a the Schur Complement stored within the data structures of the solver.
9641 
9642   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9643 
9644   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9645 
9646   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9647 
9648   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9649 
9650 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9651 @*/
9652 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9653 {
9654   PetscFunctionBegin;
9655   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9656   if (S) {
9657     PetscAssertPointer(S, 2);
9658     *S = F->schur;
9659   }
9660   if (status) {
9661     PetscAssertPointer(status, 3);
9662     *status = F->schur_status;
9663   }
9664   PetscFunctionReturn(PETSC_SUCCESS);
9665 }
9666 
9667 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9668 {
9669   Mat S = F->schur;
9670 
9671   PetscFunctionBegin;
9672   switch (F->schur_status) {
9673   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9674   case MAT_FACTOR_SCHUR_INVERTED:
9675     if (S) {
9676       S->ops->solve             = NULL;
9677       S->ops->matsolve          = NULL;
9678       S->ops->solvetranspose    = NULL;
9679       S->ops->matsolvetranspose = NULL;
9680       S->ops->solveadd          = NULL;
9681       S->ops->solvetransposeadd = NULL;
9682       S->factortype             = MAT_FACTOR_NONE;
9683       PetscCall(PetscFree(S->solvertype));
9684     }
9685   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9686     break;
9687   default:
9688     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9689   }
9690   PetscFunctionReturn(PETSC_SUCCESS);
9691 }
9692 
9693 /*@
9694   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9695 
9696   Logically Collective
9697 
9698   Input Parameters:
9699 + F      - the factored matrix obtained by calling `MatGetFactor()`
9700 . S      - location where the Schur complement is stored
9701 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9702 
9703   Level: advanced
9704 
9705 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9706 @*/
9707 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9708 {
9709   PetscFunctionBegin;
9710   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9711   if (S) {
9712     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9713     *S = NULL;
9714   }
9715   F->schur_status = status;
9716   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9717   PetscFunctionReturn(PETSC_SUCCESS);
9718 }
9719 
9720 /*@
9721   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9722 
9723   Logically Collective
9724 
9725   Input Parameters:
9726 + F   - the factored matrix obtained by calling `MatGetFactor()`
9727 . rhs - location where the right hand side of the Schur complement system is stored
9728 - sol - location where the solution of the Schur complement system has to be returned
9729 
9730   Level: advanced
9731 
9732   Notes:
9733   The sizes of the vectors should match the size of the Schur complement
9734 
9735   Must be called after `MatFactorSetSchurIS()`
9736 
9737 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9738 @*/
9739 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9740 {
9741   PetscFunctionBegin;
9742   PetscValidType(F, 1);
9743   PetscValidType(rhs, 2);
9744   PetscValidType(sol, 3);
9745   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9746   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9747   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9748   PetscCheckSameComm(F, 1, rhs, 2);
9749   PetscCheckSameComm(F, 1, sol, 3);
9750   PetscCall(MatFactorFactorizeSchurComplement(F));
9751   switch (F->schur_status) {
9752   case MAT_FACTOR_SCHUR_FACTORED:
9753     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9754     break;
9755   case MAT_FACTOR_SCHUR_INVERTED:
9756     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9757     break;
9758   default:
9759     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9760   }
9761   PetscFunctionReturn(PETSC_SUCCESS);
9762 }
9763 
9764 /*@
9765   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9766 
9767   Logically Collective
9768 
9769   Input Parameters:
9770 + F   - the factored matrix obtained by calling `MatGetFactor()`
9771 . rhs - location where the right hand side of the Schur complement system is stored
9772 - sol - location where the solution of the Schur complement system has to be returned
9773 
9774   Level: advanced
9775 
9776   Notes:
9777   The sizes of the vectors should match the size of the Schur complement
9778 
9779   Must be called after `MatFactorSetSchurIS()`
9780 
9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9782 @*/
9783 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9784 {
9785   PetscFunctionBegin;
9786   PetscValidType(F, 1);
9787   PetscValidType(rhs, 2);
9788   PetscValidType(sol, 3);
9789   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9790   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9791   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9792   PetscCheckSameComm(F, 1, rhs, 2);
9793   PetscCheckSameComm(F, 1, sol, 3);
9794   PetscCall(MatFactorFactorizeSchurComplement(F));
9795   switch (F->schur_status) {
9796   case MAT_FACTOR_SCHUR_FACTORED:
9797     PetscCall(MatSolve(F->schur, rhs, sol));
9798     break;
9799   case MAT_FACTOR_SCHUR_INVERTED:
9800     PetscCall(MatMult(F->schur, rhs, sol));
9801     break;
9802   default:
9803     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9804   }
9805   PetscFunctionReturn(PETSC_SUCCESS);
9806 }
9807 
9808 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9809 #if PetscDefined(HAVE_CUDA)
9810 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9811 #endif
9812 
9813 /* Schur status updated in the interface */
9814 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9815 {
9816   Mat S = F->schur;
9817 
9818   PetscFunctionBegin;
9819   if (S) {
9820     PetscMPIInt size;
9821     PetscBool   isdense, isdensecuda;
9822 
9823     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9824     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9825     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9826     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9827     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9828     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9829     if (isdense) {
9830       PetscCall(MatSeqDenseInvertFactors_Private(S));
9831     } else if (isdensecuda) {
9832 #if defined(PETSC_HAVE_CUDA)
9833       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9834 #endif
9835     }
9836     // HIP??????????????
9837     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9838   }
9839   PetscFunctionReturn(PETSC_SUCCESS);
9840 }
9841 
9842 /*@
9843   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9844 
9845   Logically Collective
9846 
9847   Input Parameter:
9848 . F - the factored matrix obtained by calling `MatGetFactor()`
9849 
9850   Level: advanced
9851 
9852   Notes:
9853   Must be called after `MatFactorSetSchurIS()`.
9854 
9855   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9856 
9857 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9858 @*/
9859 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9860 {
9861   PetscFunctionBegin;
9862   PetscValidType(F, 1);
9863   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9864   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9865   PetscCall(MatFactorFactorizeSchurComplement(F));
9866   PetscCall(MatFactorInvertSchurComplement_Private(F));
9867   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9868   PetscFunctionReturn(PETSC_SUCCESS);
9869 }
9870 
9871 /*@
9872   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9873 
9874   Logically Collective
9875 
9876   Input Parameter:
9877 . F - the factored matrix obtained by calling `MatGetFactor()`
9878 
9879   Level: advanced
9880 
9881   Note:
9882   Must be called after `MatFactorSetSchurIS()`
9883 
9884 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9885 @*/
9886 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9887 {
9888   MatFactorInfo info;
9889 
9890   PetscFunctionBegin;
9891   PetscValidType(F, 1);
9892   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9893   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9894   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9895   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9896   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9897     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9898   } else {
9899     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9900   }
9901   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9902   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9903   PetscFunctionReturn(PETSC_SUCCESS);
9904 }
9905 
9906 /*@
9907   MatPtAP - Creates the matrix product $C = P^T * A * P$
9908 
9909   Neighbor-wise Collective
9910 
9911   Input Parameters:
9912 + A     - the matrix
9913 . P     - the projection matrix
9914 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9915 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9916           if the result is a dense matrix this is irrelevant
9917 
9918   Output Parameter:
9919 . C - the product matrix
9920 
9921   Level: intermediate
9922 
9923   Notes:
9924   C will be created and must be destroyed by the user with `MatDestroy()`.
9925 
9926   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9927 
9928   Developer Note:
9929   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9930 
9931 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9932 @*/
9933 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9934 {
9935   PetscFunctionBegin;
9936   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9937   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9938 
9939   if (scall == MAT_INITIAL_MATRIX) {
9940     PetscCall(MatProductCreate(A, P, NULL, C));
9941     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9942     PetscCall(MatProductSetAlgorithm(*C, "default"));
9943     PetscCall(MatProductSetFill(*C, fill));
9944 
9945     (*C)->product->api_user = PETSC_TRUE;
9946     PetscCall(MatProductSetFromOptions(*C));
9947     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);
9948     PetscCall(MatProductSymbolic(*C));
9949   } else { /* scall == MAT_REUSE_MATRIX */
9950     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9951   }
9952 
9953   PetscCall(MatProductNumeric(*C));
9954   (*C)->symmetric = A->symmetric;
9955   (*C)->spd       = A->spd;
9956   PetscFunctionReturn(PETSC_SUCCESS);
9957 }
9958 
9959 /*@
9960   MatRARt - Creates the matrix product $C = R * A * R^T$
9961 
9962   Neighbor-wise Collective
9963 
9964   Input Parameters:
9965 + A     - the matrix
9966 . R     - the projection matrix
9967 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9968 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9969           if the result is a dense matrix this is irrelevant
9970 
9971   Output Parameter:
9972 . C - the product matrix
9973 
9974   Level: intermediate
9975 
9976   Notes:
9977   C will be created and must be destroyed by the user with `MatDestroy()`.
9978 
9979   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9980 
9981   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9982   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9983   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9984   We recommend using MatPtAP().
9985 
9986 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9987 @*/
9988 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9989 {
9990   PetscFunctionBegin;
9991   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9992   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9993 
9994   if (scall == MAT_INITIAL_MATRIX) {
9995     PetscCall(MatProductCreate(A, R, NULL, C));
9996     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9997     PetscCall(MatProductSetAlgorithm(*C, "default"));
9998     PetscCall(MatProductSetFill(*C, fill));
9999 
10000     (*C)->product->api_user = PETSC_TRUE;
10001     PetscCall(MatProductSetFromOptions(*C));
10002     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);
10003     PetscCall(MatProductSymbolic(*C));
10004   } else { /* scall == MAT_REUSE_MATRIX */
10005     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10006   }
10007 
10008   PetscCall(MatProductNumeric(*C));
10009   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10010   PetscFunctionReturn(PETSC_SUCCESS);
10011 }
10012 
10013 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10014 {
10015   PetscFunctionBegin;
10016   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10017 
10018   if (scall == MAT_INITIAL_MATRIX) {
10019     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10020     PetscCall(MatProductCreate(A, B, NULL, C));
10021     PetscCall(MatProductSetType(*C, ptype));
10022     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10023     PetscCall(MatProductSetFill(*C, fill));
10024 
10025     (*C)->product->api_user = PETSC_TRUE;
10026     PetscCall(MatProductSetFromOptions(*C));
10027     PetscCall(MatProductSymbolic(*C));
10028   } else { /* scall == MAT_REUSE_MATRIX */
10029     Mat_Product *product = (*C)->product;
10030     PetscBool    isdense;
10031 
10032     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10033     if (isdense && product && product->type != ptype) {
10034       PetscCall(MatProductClear(*C));
10035       product = NULL;
10036     }
10037     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10038     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10039       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10040       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10041       product           = (*C)->product;
10042       product->fill     = fill;
10043       product->api_user = PETSC_TRUE;
10044       product->clear    = PETSC_TRUE;
10045 
10046       PetscCall(MatProductSetType(*C, ptype));
10047       PetscCall(MatProductSetFromOptions(*C));
10048       PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for %s and %s", MatProductTypes[ptype], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name);
10049       PetscCall(MatProductSymbolic(*C));
10050     } else { /* user may change input matrices A or B when REUSE */
10051       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10052     }
10053   }
10054   PetscCall(MatProductNumeric(*C));
10055   PetscFunctionReturn(PETSC_SUCCESS);
10056 }
10057 
10058 /*@
10059   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10060 
10061   Neighbor-wise Collective
10062 
10063   Input Parameters:
10064 + A     - the left matrix
10065 . B     - the right matrix
10066 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10067 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10068           if the result is a dense matrix this is irrelevant
10069 
10070   Output Parameter:
10071 . C - the product matrix
10072 
10073   Notes:
10074   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10075 
10076   `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
10077   call to this function with `MAT_INITIAL_MATRIX`.
10078 
10079   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10080 
10081   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`,
10082   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10083 
10084   Example of Usage:
10085 .vb
10086      MatProductCreate(A,B,NULL,&C);
10087      MatProductSetType(C,MATPRODUCT_AB);
10088      MatProductSymbolic(C);
10089      MatProductNumeric(C); // compute C=A * B
10090      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10091      MatProductNumeric(C);
10092      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10093      MatProductNumeric(C);
10094 .ve
10095 
10096   Level: intermediate
10097 
10098 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10099 @*/
10100 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10101 {
10102   PetscFunctionBegin;
10103   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10104   PetscFunctionReturn(PETSC_SUCCESS);
10105 }
10106 
10107 /*@
10108   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10109 
10110   Neighbor-wise Collective
10111 
10112   Input Parameters:
10113 + A     - the left matrix
10114 . B     - the right matrix
10115 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10116 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10117 
10118   Output Parameter:
10119 . C - the product matrix
10120 
10121   Options Database Key:
10122 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10123               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10124               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10125 
10126   Level: intermediate
10127 
10128   Notes:
10129   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10130 
10131   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10132 
10133   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10134   actually needed.
10135 
10136   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10137   and for pairs of `MATMPIDENSE` matrices.
10138 
10139   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10140 
10141 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10142 @*/
10143 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10144 {
10145   PetscFunctionBegin;
10146   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10147   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10148   PetscFunctionReturn(PETSC_SUCCESS);
10149 }
10150 
10151 /*@
10152   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10153 
10154   Neighbor-wise Collective
10155 
10156   Input Parameters:
10157 + A     - the left matrix
10158 . B     - the right matrix
10159 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10160 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10161 
10162   Output Parameter:
10163 . C - the product matrix
10164 
10165   Level: intermediate
10166 
10167   Notes:
10168   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10169 
10170   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10171 
10172   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10173 
10174   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10175   actually needed.
10176 
10177   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10178   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10179 
10180 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10181 @*/
10182 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10183 {
10184   PetscFunctionBegin;
10185   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10186   PetscFunctionReturn(PETSC_SUCCESS);
10187 }
10188 
10189 /*@
10190   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10191 
10192   Neighbor-wise Collective
10193 
10194   Input Parameters:
10195 + A     - the left matrix
10196 . B     - the middle matrix
10197 . C     - the right matrix
10198 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10199 - 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
10200           if the result is a dense matrix this is irrelevant
10201 
10202   Output Parameter:
10203 . D - the product matrix
10204 
10205   Level: intermediate
10206 
10207   Notes:
10208   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10209 
10210   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10211 
10212   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10213 
10214   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10215   actually needed.
10216 
10217   If you have many matrices with the same non-zero structure to multiply, you
10218   should use `MAT_REUSE_MATRIX` in all calls but the first
10219 
10220 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10221 @*/
10222 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10223 {
10224   PetscFunctionBegin;
10225   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10226   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10227 
10228   if (scall == MAT_INITIAL_MATRIX) {
10229     PetscCall(MatProductCreate(A, B, C, D));
10230     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10231     PetscCall(MatProductSetAlgorithm(*D, "default"));
10232     PetscCall(MatProductSetFill(*D, fill));
10233 
10234     (*D)->product->api_user = PETSC_TRUE;
10235     PetscCall(MatProductSetFromOptions(*D));
10236     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,
10237                ((PetscObject)C)->type_name);
10238     PetscCall(MatProductSymbolic(*D));
10239   } else { /* user may change input matrices when REUSE */
10240     PetscCall(MatProductReplaceMats(A, B, C, *D));
10241   }
10242   PetscCall(MatProductNumeric(*D));
10243   PetscFunctionReturn(PETSC_SUCCESS);
10244 }
10245 
10246 /*@
10247   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10248 
10249   Collective
10250 
10251   Input Parameters:
10252 + mat      - the matrix
10253 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10254 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10255 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10256 
10257   Output Parameter:
10258 . matredundant - redundant matrix
10259 
10260   Level: advanced
10261 
10262   Notes:
10263   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10264   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10265 
10266   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10267   calling it.
10268 
10269   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10270 
10271 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10272 @*/
10273 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10274 {
10275   MPI_Comm       comm;
10276   PetscMPIInt    size;
10277   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10278   Mat_Redundant *redund     = NULL;
10279   PetscSubcomm   psubcomm   = NULL;
10280   MPI_Comm       subcomm_in = subcomm;
10281   Mat           *matseq;
10282   IS             isrow, iscol;
10283   PetscBool      newsubcomm = PETSC_FALSE;
10284 
10285   PetscFunctionBegin;
10286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10287   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10288     PetscAssertPointer(*matredundant, 5);
10289     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10290   }
10291 
10292   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10293   if (size == 1 || nsubcomm == 1) {
10294     if (reuse == MAT_INITIAL_MATRIX) {
10295       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10296     } else {
10297       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");
10298       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10299     }
10300     PetscFunctionReturn(PETSC_SUCCESS);
10301   }
10302 
10303   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10304   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10305   MatCheckPreallocated(mat, 1);
10306 
10307   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10308   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10309     /* create psubcomm, then get subcomm */
10310     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10311     PetscCallMPI(MPI_Comm_size(comm, &size));
10312     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10313 
10314     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10315     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10316     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10317     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10318     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10319     newsubcomm = PETSC_TRUE;
10320     PetscCall(PetscSubcommDestroy(&psubcomm));
10321   }
10322 
10323   /* get isrow, iscol and a local sequential matrix matseq[0] */
10324   if (reuse == MAT_INITIAL_MATRIX) {
10325     mloc_sub = PETSC_DECIDE;
10326     nloc_sub = PETSC_DECIDE;
10327     if (bs < 1) {
10328       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10329       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10330     } else {
10331       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10332       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10333     }
10334     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10335     rstart = rend - mloc_sub;
10336     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10337     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10338     PetscCall(ISSetIdentity(iscol));
10339   } else { /* reuse == MAT_REUSE_MATRIX */
10340     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");
10341     /* retrieve subcomm */
10342     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10343     redund = (*matredundant)->redundant;
10344     isrow  = redund->isrow;
10345     iscol  = redund->iscol;
10346     matseq = redund->matseq;
10347   }
10348   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10349 
10350   /* get matredundant over subcomm */
10351   if (reuse == MAT_INITIAL_MATRIX) {
10352     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10353 
10354     /* create a supporting struct and attach it to C for reuse */
10355     PetscCall(PetscNew(&redund));
10356     (*matredundant)->redundant = redund;
10357     redund->isrow              = isrow;
10358     redund->iscol              = iscol;
10359     redund->matseq             = matseq;
10360     if (newsubcomm) {
10361       redund->subcomm = subcomm;
10362     } else {
10363       redund->subcomm = MPI_COMM_NULL;
10364     }
10365   } else {
10366     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10367   }
10368 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10369   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10370     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10371     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10372   }
10373 #endif
10374   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10375   PetscFunctionReturn(PETSC_SUCCESS);
10376 }
10377 
10378 /*@C
10379   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10380   a given `Mat`. Each submatrix can span multiple procs.
10381 
10382   Collective
10383 
10384   Input Parameters:
10385 + mat     - the matrix
10386 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10387 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10388 
10389   Output Parameter:
10390 . subMat - parallel sub-matrices each spanning a given `subcomm`
10391 
10392   Level: advanced
10393 
10394   Notes:
10395   The submatrix partition across processors is dictated by `subComm` a
10396   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10397   is not restricted to be grouped with consecutive original MPI processes.
10398 
10399   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10400   map directly to the layout of the original matrix [wrt the local
10401   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10402   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10403   the `subMat`. However the offDiagMat looses some columns - and this is
10404   reconstructed with `MatSetValues()`
10405 
10406   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10407 
10408 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10409 @*/
10410 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10411 {
10412   PetscMPIInt commsize, subCommSize;
10413 
10414   PetscFunctionBegin;
10415   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10416   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10417   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10418 
10419   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");
10420   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10421   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10422   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10423   PetscFunctionReturn(PETSC_SUCCESS);
10424 }
10425 
10426 /*@
10427   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10428 
10429   Not Collective
10430 
10431   Input Parameters:
10432 + mat   - matrix to extract local submatrix from
10433 . isrow - local row indices for submatrix
10434 - iscol - local column indices for submatrix
10435 
10436   Output Parameter:
10437 . submat - the submatrix
10438 
10439   Level: intermediate
10440 
10441   Notes:
10442   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10443 
10444   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10445   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10446 
10447   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10448   `MatSetValuesBlockedLocal()` will also be implemented.
10449 
10450   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10451   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10452 
10453 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10454 @*/
10455 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10456 {
10457   PetscFunctionBegin;
10458   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10459   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10460   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10461   PetscCheckSameComm(isrow, 2, iscol, 3);
10462   PetscAssertPointer(submat, 4);
10463   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10464 
10465   if (mat->ops->getlocalsubmatrix) {
10466     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10467   } else {
10468     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10469   }
10470   PetscFunctionReturn(PETSC_SUCCESS);
10471 }
10472 
10473 /*@
10474   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10475 
10476   Not Collective
10477 
10478   Input Parameters:
10479 + mat    - matrix to extract local submatrix from
10480 . isrow  - local row indices for submatrix
10481 . iscol  - local column indices for submatrix
10482 - submat - the submatrix
10483 
10484   Level: intermediate
10485 
10486 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10487 @*/
10488 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10489 {
10490   PetscFunctionBegin;
10491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10492   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10493   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10494   PetscCheckSameComm(isrow, 2, iscol, 3);
10495   PetscAssertPointer(submat, 4);
10496   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10497 
10498   if (mat->ops->restorelocalsubmatrix) {
10499     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10500   } else {
10501     PetscCall(MatDestroy(submat));
10502   }
10503   *submat = NULL;
10504   PetscFunctionReturn(PETSC_SUCCESS);
10505 }
10506 
10507 /*@
10508   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10509 
10510   Collective
10511 
10512   Input Parameter:
10513 . mat - the matrix
10514 
10515   Output Parameter:
10516 . is - if any rows have zero diagonals this contains the list of them
10517 
10518   Level: developer
10519 
10520 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10521 @*/
10522 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10523 {
10524   PetscFunctionBegin;
10525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10526   PetscValidType(mat, 1);
10527   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10528   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10529 
10530   if (!mat->ops->findzerodiagonals) {
10531     Vec                diag;
10532     const PetscScalar *a;
10533     PetscInt          *rows;
10534     PetscInt           rStart, rEnd, r, nrow = 0;
10535 
10536     PetscCall(MatCreateVecs(mat, &diag, NULL));
10537     PetscCall(MatGetDiagonal(mat, diag));
10538     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10539     PetscCall(VecGetArrayRead(diag, &a));
10540     for (r = 0; r < rEnd - rStart; ++r)
10541       if (a[r] == 0.0) ++nrow;
10542     PetscCall(PetscMalloc1(nrow, &rows));
10543     nrow = 0;
10544     for (r = 0; r < rEnd - rStart; ++r)
10545       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10546     PetscCall(VecRestoreArrayRead(diag, &a));
10547     PetscCall(VecDestroy(&diag));
10548     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10549   } else {
10550     PetscUseTypeMethod(mat, findzerodiagonals, is);
10551   }
10552   PetscFunctionReturn(PETSC_SUCCESS);
10553 }
10554 
10555 /*@
10556   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10557 
10558   Collective
10559 
10560   Input Parameter:
10561 . mat - the matrix
10562 
10563   Output Parameter:
10564 . is - contains the list of rows with off block diagonal entries
10565 
10566   Level: developer
10567 
10568 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10569 @*/
10570 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10571 {
10572   PetscFunctionBegin;
10573   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10574   PetscValidType(mat, 1);
10575   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10576   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10577 
10578   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10579   PetscFunctionReturn(PETSC_SUCCESS);
10580 }
10581 
10582 /*@C
10583   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10584 
10585   Collective; No Fortran Support
10586 
10587   Input Parameter:
10588 . mat - the matrix
10589 
10590   Output Parameter:
10591 . values - the block inverses in column major order (FORTRAN-like)
10592 
10593   Level: advanced
10594 
10595   Notes:
10596   The size of the blocks is determined by the block size of the matrix.
10597 
10598   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10599 
10600   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10601 
10602 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10603 @*/
10604 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10605 {
10606   PetscFunctionBegin;
10607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10608   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10609   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10610   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10611   PetscFunctionReturn(PETSC_SUCCESS);
10612 }
10613 
10614 /*@C
10615   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10616 
10617   Collective; No Fortran Support
10618 
10619   Input Parameters:
10620 + mat     - the matrix
10621 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10622 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10623 
10624   Output Parameter:
10625 . values - the block inverses in column major order (FORTRAN-like)
10626 
10627   Level: advanced
10628 
10629   Notes:
10630   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10631 
10632   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10633 
10634 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10635 @*/
10636 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10637 {
10638   PetscFunctionBegin;
10639   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10640   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10641   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10642   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10643   PetscFunctionReturn(PETSC_SUCCESS);
10644 }
10645 
10646 /*@
10647   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10648 
10649   Collective
10650 
10651   Input Parameters:
10652 + A - the matrix
10653 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10654 
10655   Level: advanced
10656 
10657   Note:
10658   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10659 
10660 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10661 @*/
10662 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10663 {
10664   const PetscScalar *vals;
10665   PetscInt          *dnnz;
10666   PetscInt           m, rstart, rend, bs, i, j;
10667 
10668   PetscFunctionBegin;
10669   PetscCall(MatInvertBlockDiagonal(A, &vals));
10670   PetscCall(MatGetBlockSize(A, &bs));
10671   PetscCall(MatGetLocalSize(A, &m, NULL));
10672   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10673   PetscCall(PetscMalloc1(m / bs, &dnnz));
10674   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10675   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10676   PetscCall(PetscFree(dnnz));
10677   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10678   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10679   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10680   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10681   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10682   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10683   PetscFunctionReturn(PETSC_SUCCESS);
10684 }
10685 
10686 /*@C
10687   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10688   via `MatTransposeColoringCreate()`.
10689 
10690   Collective
10691 
10692   Input Parameter:
10693 . c - coloring context
10694 
10695   Level: intermediate
10696 
10697 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10698 @*/
10699 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10700 {
10701   MatTransposeColoring matcolor = *c;
10702 
10703   PetscFunctionBegin;
10704   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10705   if (--((PetscObject)matcolor)->refct > 0) {
10706     matcolor = NULL;
10707     PetscFunctionReturn(PETSC_SUCCESS);
10708   }
10709 
10710   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10711   PetscCall(PetscFree(matcolor->rows));
10712   PetscCall(PetscFree(matcolor->den2sp));
10713   PetscCall(PetscFree(matcolor->colorforcol));
10714   PetscCall(PetscFree(matcolor->columns));
10715   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10716   PetscCall(PetscHeaderDestroy(c));
10717   PetscFunctionReturn(PETSC_SUCCESS);
10718 }
10719 
10720 /*@C
10721   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10722   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10723   `MatTransposeColoring` to sparse `B`.
10724 
10725   Collective
10726 
10727   Input Parameters:
10728 + coloring - coloring context created with `MatTransposeColoringCreate()`
10729 - B        - sparse matrix
10730 
10731   Output Parameter:
10732 . Btdense - dense matrix $B^T$
10733 
10734   Level: developer
10735 
10736   Note:
10737   These are used internally for some implementations of `MatRARt()`
10738 
10739 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10740 @*/
10741 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10742 {
10743   PetscFunctionBegin;
10744   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10745   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10746   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10747 
10748   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10749   PetscFunctionReturn(PETSC_SUCCESS);
10750 }
10751 
10752 /*@C
10753   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10754   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10755   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10756   $C_{sp}$ from $C_{den}$.
10757 
10758   Collective
10759 
10760   Input Parameters:
10761 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10762 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10763 
10764   Output Parameter:
10765 . Csp - sparse matrix
10766 
10767   Level: developer
10768 
10769   Note:
10770   These are used internally for some implementations of `MatRARt()`
10771 
10772 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10773 @*/
10774 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10775 {
10776   PetscFunctionBegin;
10777   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10778   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10779   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10780 
10781   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10782   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10783   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10784   PetscFunctionReturn(PETSC_SUCCESS);
10785 }
10786 
10787 /*@C
10788   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10789 
10790   Collective
10791 
10792   Input Parameters:
10793 + mat        - the matrix product C
10794 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10795 
10796   Output Parameter:
10797 . color - the new coloring context
10798 
10799   Level: intermediate
10800 
10801 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10802           `MatTransColoringApplyDenToSp()`
10803 @*/
10804 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10805 {
10806   MatTransposeColoring c;
10807   MPI_Comm             comm;
10808 
10809   PetscFunctionBegin;
10810   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10811   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10812   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10813 
10814   c->ctype = iscoloring->ctype;
10815   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10816 
10817   *color = c;
10818   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10819   PetscFunctionReturn(PETSC_SUCCESS);
10820 }
10821 
10822 /*@
10823   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10824   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10825   same, otherwise it will be larger
10826 
10827   Not Collective
10828 
10829   Input Parameter:
10830 . mat - the matrix
10831 
10832   Output Parameter:
10833 . state - the current state
10834 
10835   Level: intermediate
10836 
10837   Notes:
10838   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10839   different matrices
10840 
10841   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10842 
10843   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10844 
10845 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10846 @*/
10847 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10848 {
10849   PetscFunctionBegin;
10850   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10851   *state = mat->nonzerostate;
10852   PetscFunctionReturn(PETSC_SUCCESS);
10853 }
10854 
10855 /*@
10856   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10857   matrices from each processor
10858 
10859   Collective
10860 
10861   Input Parameters:
10862 + comm   - the communicators the parallel matrix will live on
10863 . seqmat - the input sequential matrices
10864 . n      - number of local columns (or `PETSC_DECIDE`)
10865 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10866 
10867   Output Parameter:
10868 . mpimat - the parallel matrix generated
10869 
10870   Level: developer
10871 
10872   Note:
10873   The number of columns of the matrix in EACH processor MUST be the same.
10874 
10875 .seealso: [](ch_matrices), `Mat`
10876 @*/
10877 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10878 {
10879   PetscMPIInt size;
10880 
10881   PetscFunctionBegin;
10882   PetscCallMPI(MPI_Comm_size(comm, &size));
10883   if (size == 1) {
10884     if (reuse == MAT_INITIAL_MATRIX) {
10885       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10886     } else {
10887       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10888     }
10889     PetscFunctionReturn(PETSC_SUCCESS);
10890   }
10891 
10892   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");
10893 
10894   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10895   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10896   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10897   PetscFunctionReturn(PETSC_SUCCESS);
10898 }
10899 
10900 /*@
10901   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10902 
10903   Collective
10904 
10905   Input Parameters:
10906 + A - the matrix to create subdomains from
10907 - N - requested number of subdomains
10908 
10909   Output Parameters:
10910 + n   - number of subdomains resulting on this MPI process
10911 - iss - `IS` list with indices of subdomains on this MPI process
10912 
10913   Level: advanced
10914 
10915   Note:
10916   The number of subdomains must be smaller than the communicator size
10917 
10918 .seealso: [](ch_matrices), `Mat`, `IS`
10919 @*/
10920 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10921 {
10922   MPI_Comm    comm, subcomm;
10923   PetscMPIInt size, rank, color;
10924   PetscInt    rstart, rend, k;
10925 
10926   PetscFunctionBegin;
10927   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10928   PetscCallMPI(MPI_Comm_size(comm, &size));
10929   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10930   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);
10931   *n    = 1;
10932   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10933   color = rank / k;
10934   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10935   PetscCall(PetscMalloc1(1, iss));
10936   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10937   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10938   PetscCallMPI(MPI_Comm_free(&subcomm));
10939   PetscFunctionReturn(PETSC_SUCCESS);
10940 }
10941 
10942 /*@
10943   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10944 
10945   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10946   If they are not the same, uses `MatMatMatMult()`.
10947 
10948   Once the coarse grid problem is constructed, correct for interpolation operators
10949   that are not of full rank, which can legitimately happen in the case of non-nested
10950   geometric multigrid.
10951 
10952   Input Parameters:
10953 + restrct     - restriction operator
10954 . dA          - fine grid matrix
10955 . interpolate - interpolation operator
10956 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10957 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10958 
10959   Output Parameter:
10960 . A - the Galerkin coarse matrix
10961 
10962   Options Database Key:
10963 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10964 
10965   Level: developer
10966 
10967 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10968 @*/
10969 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10970 {
10971   IS  zerorows;
10972   Vec diag;
10973 
10974   PetscFunctionBegin;
10975   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10976   /* Construct the coarse grid matrix */
10977   if (interpolate == restrct) {
10978     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10979   } else {
10980     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10981   }
10982 
10983   /* If the interpolation matrix is not of full rank, A will have zero rows.
10984      This can legitimately happen in the case of non-nested geometric multigrid.
10985      In that event, we set the rows of the matrix to the rows of the identity,
10986      ignoring the equations (as the RHS will also be zero). */
10987 
10988   PetscCall(MatFindZeroRows(*A, &zerorows));
10989 
10990   if (zerorows != NULL) { /* if there are any zero rows */
10991     PetscCall(MatCreateVecs(*A, &diag, NULL));
10992     PetscCall(MatGetDiagonal(*A, diag));
10993     PetscCall(VecISSet(diag, zerorows, 1.0));
10994     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10995     PetscCall(VecDestroy(&diag));
10996     PetscCall(ISDestroy(&zerorows));
10997   }
10998   PetscFunctionReturn(PETSC_SUCCESS);
10999 }
11000 
11001 /*@C
11002   MatSetOperation - Allows user to set a matrix operation for any matrix type
11003 
11004   Logically Collective
11005 
11006   Input Parameters:
11007 + mat - the matrix
11008 . op  - the name of the operation
11009 - f   - the function that provides the operation
11010 
11011   Level: developer
11012 
11013   Example Usage:
11014 .vb
11015   extern PetscErrorCode usermult(Mat, Vec, Vec);
11016 
11017   PetscCall(MatCreateXXX(comm, ..., &A));
11018   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
11019 .ve
11020 
11021   Notes:
11022   See the file `include/petscmat.h` for a complete list of matrix
11023   operations, which all have the form MATOP_<OPERATION>, where
11024   <OPERATION> is the name (in all capital letters) of the
11025   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11026 
11027   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11028   sequence as the usual matrix interface routines, since they
11029   are intended to be accessed via the usual matrix interface
11030   routines, e.g.,
11031 .vb
11032   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11033 .ve
11034 
11035   In particular each function MUST return `PETSC_SUCCESS` on success and
11036   nonzero on failure.
11037 
11038   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11039 
11040 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11041 @*/
11042 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11043 {
11044   PetscFunctionBegin;
11045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11046   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11047   (((void (**)(void))mat->ops)[op]) = f;
11048   PetscFunctionReturn(PETSC_SUCCESS);
11049 }
11050 
11051 /*@C
11052   MatGetOperation - Gets a matrix operation for any matrix type.
11053 
11054   Not Collective
11055 
11056   Input Parameters:
11057 + mat - the matrix
11058 - op  - the name of the operation
11059 
11060   Output Parameter:
11061 . f - the function that provides the operation
11062 
11063   Level: developer
11064 
11065   Example Usage:
11066 .vb
11067   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11068 
11069   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11070 .ve
11071 
11072   Notes:
11073   See the file include/petscmat.h for a complete list of matrix
11074   operations, which all have the form MATOP_<OPERATION>, where
11075   <OPERATION> is the name (in all capital letters) of the
11076   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11077 
11078   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11079 
11080 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11081 @*/
11082 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11083 {
11084   PetscFunctionBegin;
11085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11086   *f = (((void (**)(void))mat->ops)[op]);
11087   PetscFunctionReturn(PETSC_SUCCESS);
11088 }
11089 
11090 /*@
11091   MatHasOperation - Determines whether the given matrix supports the particular operation.
11092 
11093   Not Collective
11094 
11095   Input Parameters:
11096 + mat - the matrix
11097 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11098 
11099   Output Parameter:
11100 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11101 
11102   Level: advanced
11103 
11104   Note:
11105   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11106 
11107 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11108 @*/
11109 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11110 {
11111   PetscFunctionBegin;
11112   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11113   PetscAssertPointer(has, 3);
11114   if (mat->ops->hasoperation) {
11115     PetscUseTypeMethod(mat, hasoperation, op, has);
11116   } else {
11117     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11118     else {
11119       *has = PETSC_FALSE;
11120       if (op == MATOP_CREATE_SUBMATRIX) {
11121         PetscMPIInt size;
11122 
11123         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11124         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11125       }
11126     }
11127   }
11128   PetscFunctionReturn(PETSC_SUCCESS);
11129 }
11130 
11131 /*@
11132   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11133 
11134   Collective
11135 
11136   Input Parameter:
11137 . mat - the matrix
11138 
11139   Output Parameter:
11140 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11141 
11142   Level: beginner
11143 
11144 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11145 @*/
11146 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11147 {
11148   PetscFunctionBegin;
11149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11150   PetscValidType(mat, 1);
11151   PetscAssertPointer(cong, 2);
11152   if (!mat->rmap || !mat->cmap) {
11153     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11154     PetscFunctionReturn(PETSC_SUCCESS);
11155   }
11156   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11157     PetscCall(PetscLayoutSetUp(mat->rmap));
11158     PetscCall(PetscLayoutSetUp(mat->cmap));
11159     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11160     if (*cong) mat->congruentlayouts = 1;
11161     else mat->congruentlayouts = 0;
11162   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11163   PetscFunctionReturn(PETSC_SUCCESS);
11164 }
11165 
11166 PetscErrorCode MatSetInf(Mat A)
11167 {
11168   PetscFunctionBegin;
11169   PetscUseTypeMethod(A, setinf);
11170   PetscFunctionReturn(PETSC_SUCCESS);
11171 }
11172 
11173 /*@C
11174   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
11175   and possibly removes small values from the graph structure.
11176 
11177   Collective
11178 
11179   Input Parameters:
11180 + A      - the matrix
11181 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11182 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11183 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11184 
11185   Output Parameter:
11186 . graph - the resulting graph
11187 
11188   Level: advanced
11189 
11190 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11191 @*/
11192 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11193 {
11194   PetscFunctionBegin;
11195   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11196   PetscValidType(A, 1);
11197   PetscValidLogicalCollectiveBool(A, scale, 3);
11198   PetscAssertPointer(graph, 5);
11199   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11200   PetscFunctionReturn(PETSC_SUCCESS);
11201 }
11202 
11203 /*@
11204   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11205   meaning the same memory is used for the matrix, and no new memory is allocated.
11206 
11207   Collective
11208 
11209   Input Parameters:
11210 + A    - the matrix
11211 - 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
11212 
11213   Level: intermediate
11214 
11215   Developer Note:
11216   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11217   of the arrays in the data structure are unneeded.
11218 
11219 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11220 @*/
11221 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11222 {
11223   PetscFunctionBegin;
11224   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11225   PetscUseTypeMethod(A, eliminatezeros, keep);
11226   PetscFunctionReturn(PETSC_SUCCESS);
11227 }
11228